[xiph-commits] r17105 - experimental/derf/theora-ptalarbvorm/lib

gmaxwell at svn.xiph.org gmaxwell at svn.xiph.org
Thu Apr 1 06:57:23 PDT 2010


Author: gmaxwell
Date: 2010-04-01 06:57:23 -0700 (Thu, 01 Apr 2010)
New Revision: 17105

Modified:
   experimental/derf/theora-ptalarbvorm/lib/analyze.c
   experimental/derf/theora-ptalarbvorm/lib/encode.c
   experimental/derf/theora-ptalarbvorm/lib/internal.h
   experimental/derf/theora-ptalarbvorm/lib/mcenc.c
   experimental/derf/theora-ptalarbvorm/lib/state.c
Log:
This change makes the original frames available as references (in addition to the decoded frames) and uses them for the coarse 1px motion search. Searching against the original frames isn't an improvement on its own, but it makes a number of further quality and performance improvements possible.

Modified: experimental/derf/theora-ptalarbvorm/lib/analyze.c
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/analyze.c	2010-04-01 11:33:15 UTC (rev 17104)
+++ experimental/derf/theora-ptalarbvorm/lib/analyze.c	2010-04-01 13:57:23 UTC (rev 17105)
@@ -769,7 +769,7 @@
   frags=_enc->state.frags;
   frag_offs=_enc->state.frag_buf_offs[_fragi];
   ystride=_enc->state.ref_ystride[_pli];
-  src=_enc->state.ref_frame_data[OC_FRAME_IO]+frag_offs;
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]]+frag_offs;
   borderi=frags[_fragi].borderi;
   qii=frags[_fragi].qii;
   if(qii&~3){
@@ -1185,7 +1185,7 @@
   int                    bi;
   frag_buf_offs=_enc->state.frag_buf_offs;
   sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ystride=_enc->state.ref_ystride[0];
   luma=0;
   for(bi=0;bi<4;bi++){
@@ -1392,7 +1392,7 @@
   int                  bi;
   frag_buf_offs=_enc->state.frag_buf_offs;
   sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ystride=_enc->state.ref_ystride[0];
   fragi=sb_maps[_mbi>>2][_mbi&3][0];
   frag_offs=frag_buf_offs[fragi];
@@ -1481,7 +1481,7 @@
   int                  lambda;
   int                  ystride;
   int                  nqis;
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ystride=_enc->state.ref_ystride[_pli];
   frag_offs=_enc->state.frag_buf_offs[_fragi];
   satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
@@ -1920,7 +1920,7 @@
   ptrdiff_t               frag_offs;
   int                     borderi;
   int                     pi;
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
   ystride=_enc->state.ref_ystride[0];
   frags=_enc->state.frags;
@@ -2020,7 +2020,7 @@
   unsigned               dc;
   frag_buf_offs=_enc->state.frag_buf_offs;
   sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ystride=_enc->state.ref_ystride[0];
   for(bi=0;bi<4;bi++){
     fragi=sb_map[bi];
@@ -2077,7 +2077,7 @@
   ptrdiff_t              fragi;
   ptrdiff_t              frag_offs;
   unsigned               dc;
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ref=_enc->state.ref_frame_data[
    _enc->state.ref_frame_idx[OC_FRAME_FOR_MODE(_mb_mode)]];
   ystride=_enc->state.ref_ystride[0];
@@ -2195,7 +2195,7 @@
   int                    bits1;
   unsigned               satd;
   unsigned               dc;
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
   ystride=_enc->state.ref_ystride[0];
   frag_buf_offs=_enc->state.frag_buf_offs;

Modified: experimental/derf/theora-ptalarbvorm/lib/encode.c
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/encode.c	2010-04-01 11:33:15 UTC (rev 17104)
+++ experimental/derf/theora-ptalarbvorm/lib/encode.c	2010-04-01 13:57:23 UTC (rev 17105)
@@ -1099,7 +1099,7 @@
   if(info.quality<0)info.quality=32;
   if(info.target_bitrate<0)info.target_bitrate=0;
   /*Initialize the shared encoder/decoder state.*/
-  ret=oc_state_init(&_enc->state,&info,4);
+  ret=oc_state_init(&_enc->state,&info,6);
   if(ret<0)return ret;
   _enc->mb_info=_ogg_calloc(_enc->state.nmbs,sizeof(*_enc->mb_info));
   _enc->frag_dc=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_dc));
@@ -1588,21 +1588,7 @@
     img[1].data-=cpic_y*(ptrdiff_t)img[1].stride+cpic_x;
     img[2].data-=cpic_y*(ptrdiff_t)img[2].stride+cpic_x;
   }
-  /*Step 2: Copy the input to our internal buffer.
-    This lets us add padding, so we don't have to worry about dereferencing
-     possibly invalid addresses, and allows us to use the same strides and
-     fragment offsets for both the input frame and the reference frames.*/
-  oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+0,img+0,
-   pic_x,pic_y,pic_width,pic_height);
-  oc_state_borders_fill_rows(&_enc->state,OC_FRAME_IO,0,0,frame_height);
-  oc_state_borders_fill_caps(&_enc->state,OC_FRAME_IO,0);
-  for(pli=1;pli<3;pli++){
-    oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+pli,img+pli,
-     cpic_x,cpic_y,cpic_width,cpic_height);
-    oc_state_borders_fill_rows(&_enc->state,OC_FRAME_IO,pli,0,cframe_height);
-    oc_state_borders_fill_caps(&_enc->state,OC_FRAME_IO,pli);
-  }
-  /*Step 3: Update the buffer state.*/
+  /*Step 2: Update the buffer state.*/
   if(_enc->state.ref_frame_idx[OC_FRAME_SELF]>=0){
     _enc->state.ref_frame_idx[OC_FRAME_PREV]=
      _enc->state.ref_frame_idx[OC_FRAME_SELF];
@@ -1613,6 +1599,34 @@
        _enc->state.ref_frame_idx[OC_FRAME_SELF];
     }
   }
+  if(_enc->prevframe_dropped==0 && 
+     _enc->state.ref_frame_idx[OC_FRAME_IO]>=0){
+    _enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG]=
+     _enc->state.ref_frame_idx[OC_FRAME_IO];
+    if(_enc->state.frame_type==OC_INTRA_FRAME){
+      /*The input new frame becomes both the previous and gold original-reference frames.*/
+      _enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]=
+       _enc->state.ref_frame_idx[OC_FRAME_IO];
+    }
+  }  
+  /*Select a free buffer to use for the incoming frame*/
+  for(refi=3;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]||
+   refi==_enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG];refi++);
+  _enc->state.ref_frame_idx[OC_FRAME_IO]=refi;
+  /*Step 3: Copy the input to our internal buffer.
+    This lets us add padding, so we don't have to worry about dereferencing
+     possibly invalid addresses, and allows us to use the same strides and
+     fragment offsets for both the input frame and the reference frames.*/
+  oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[_enc->state.ref_frame_idx[OC_FRAME_IO]]+0,img+0,
+   pic_x,pic_y,pic_width,pic_height);
+  oc_state_borders_fill_rows(&_enc->state,_enc->state.ref_frame_idx[OC_FRAME_IO],0,0,frame_height);
+  oc_state_borders_fill_caps(&_enc->state,_enc->state.ref_frame_idx[OC_FRAME_IO],0);
+  for(pli=1;pli<3;pli++){
+    oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[_enc->state.ref_frame_idx[OC_FRAME_IO]]+pli,img+pli,
+     cpic_x,cpic_y,cpic_width,cpic_height);
+    oc_state_borders_fill_rows(&_enc->state,_enc->state.ref_frame_idx[OC_FRAME_IO],pli,0,cframe_height);
+    oc_state_borders_fill_caps(&_enc->state,_enc->state.ref_frame_idx[OC_FRAME_IO],pli);
+  }
   /*Select a free buffer to use for the reconstructed version of this frame.*/
   for(refi=0;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD]||
    refi==_enc->state.ref_frame_idx[OC_FRAME_PREV];refi++);

Modified: experimental/derf/theora-ptalarbvorm/lib/internal.h
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/internal.h	2010-04-01 11:33:15 UTC (rev 17104)
+++ experimental/derf/theora-ptalarbvorm/lib/internal.h	2010-04-01 13:57:23 UTC (rev 17105)
@@ -106,6 +106,10 @@
 
 /*The input or output buffer.*/
 #define OC_FRAME_IO   (3)
+/*Uncompressed prev golden frame.*/
+#define OC_FRAME_GOLD_ORIG (4)
+/*Uncompressed previous frame. */
+#define OC_FRAME_PREV_ORIG (5)
 
 /*Macroblock modes.*/
 /*Macro block is invalid: It is never coded.*/
@@ -346,11 +350,11 @@
   /*The total number of coded fragments.*/
   ptrdiff_t           ntotal_coded_fragis;
   /*The index of the buffers being used for each OC_FRAME_* reference frame.*/
-  int                 ref_frame_idx[4];
-  /*The actual buffers used for the previously decoded frames.*/
-  th_ycbcr_buffer     ref_frame_bufs[4];
+  int                 ref_frame_idx[6];
+  /*The actual buffers used for the reference frames.*/
+  th_ycbcr_buffer     ref_frame_bufs[6];
   /*The storage for the reference frame buffers.*/
-  unsigned char      *ref_frame_data[4];
+  unsigned char      *ref_frame_data[6];
   /*The strides for each plane in the reference frames.*/
   int                 ref_ystride[3];
   /*The number of unique border patterns.*/

Modified: experimental/derf/theora-ptalarbvorm/lib/mcenc.c
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/mcenc.c	2010-04-01 11:33:15 UTC (rev 17104)
+++ experimental/derf/theora-ptalarbvorm/lib/mcenc.c	2010-04-01 13:57:23 UTC (rev 17105)
@@ -246,11 +246,15 @@
    the work can be shared.
   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_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
+  _mcenc:      The motion compensation context.
+  _accum:      Drop frame/golden MV accumulators.
+  _mbi:        The macro block index.
+  _frame:      The frame to use for SATD calculations and refinement,
+               either OC_FRAME_PREV or OC_FRAME_GOLD.
+  _frame_full: The frame to perform the 1px search on, one of OC_FRAME_PREV,
+               OC_FRAME_GOLD, OC_FRAME_PREV_ORIG, or OC_FRAME_GOLD_ORIG.
+  */
+void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame, int _frame_full){
   /*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,
@@ -271,6 +275,7 @@
   const ptrdiff_t     *fragis;
   const unsigned char *src;
   const unsigned char *ref;
+  const unsigned char *ref_satd;
   int                  ystride;
   oc_mb_enc_info      *embs;
   ogg_int32_t          hit_cache[31];
@@ -294,8 +299,9 @@
   hit_cache[candy+15]|=(ogg_int32_t)1<<candx+15;
   frag_buf_offs=_enc->state.frag_buf_offs;
   fragis=_enc->state.mb_maps[_mbi][0];
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
-  ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
+  ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame_full]];
+  ref_satd=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]];
   ystride=_enc->state.ref_ystride[0];
   /*TODO: customize error function for speed/(quality+size) tradeoff.*/
   best_err=oc_mcenc_ysad_check_mbcandidate_fullpel(_enc,
@@ -482,7 +488,7 @@
   candx=best_vec[0];
   candy=best_vec[1];
   embs[_mbi].satd[_frame]=oc_mcenc_ysatd_check_mbcandidate_fullpel(_enc,
-   frag_buf_offs,fragis,candx,candy,src,ref,ystride);
+   frag_buf_offs,fragis,candx,candy,src,ref_satd,ystride);
   embs[_mbi].analysis_mv[0][_frame][0]=(signed char)(candx<<1);
   embs[_mbi].analysis_mv[0][_frame][1]=(signed char)(candy<<1);
   if(_frame==OC_FRAME_PREV){
@@ -490,7 +496,7 @@
       candx=best_block_vec[bi][0];
       candy=best_block_vec[bi][1];
       embs[_mbi].block_satd[bi]=oc_mcenc_ysatd_check_bcandidate_fullpel(_enc,
-       frag_buf_offs[fragis[bi]],candx,candy,src,ref,ystride);
+       frag_buf_offs[fragis[bi]],candx,candy,src,ref_satd,ystride);
       embs[_mbi].block_mv[bi][0]=(signed char)(candx<<1);
       embs[_mbi].block_mv[bi][1]=(signed char)(candy<<1);
     }
@@ -514,7 +520,7 @@
   /*Move the motion vector predictors back a frame.*/
   memmove(mvs+1,mvs,2*sizeof(*mvs));
   /*Search the last frame.*/
-  oc_mcenc_search_frame(_enc,accum_p,_mbi,OC_FRAME_PREV);
+  oc_mcenc_search_frame(_enc,accum_p,_mbi,OC_FRAME_PREV,OC_FRAME_PREV_ORIG);
   mvs[2][OC_FRAME_PREV][0]=accum_p[0];
   mvs[2][OC_FRAME_PREV][1]=accum_p[1];
   /*GOLDEN MVs are different from PREV MVs in that they're each absolute
@@ -527,7 +533,7 @@
   mvs[2][OC_FRAME_GOLD][0]-=accum_g[0];
   mvs[2][OC_FRAME_GOLD][1]-=accum_g[1];
   /*Search the golden frame.*/
-  oc_mcenc_search_frame(_enc,accum_g,_mbi,OC_FRAME_GOLD);
+  oc_mcenc_search_frame(_enc,accum_g,_mbi,OC_FRAME_GOLD,OC_FRAME_GOLD_ORIG);
   /*Put GOLDEN MVs back into absolute offset form.
     The newest MV is already an absolute offset.*/
   mvs[2][OC_FRAME_GOLD][0]+=accum_g[0];
@@ -549,7 +555,7 @@
   int                  best_site;
   int                  sitei;
   int                  err;
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_framei]];
   frag_buf_offs=_enc->state.frag_buf_offs;
   fragis=_enc->state.mb_maps[_mbi][0];
@@ -604,7 +610,7 @@
   int                  best_site;
   int                  sitei;
   int                  err;
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]];
   frag_buf_offs=_enc->state.frag_buf_offs;
   fragis=_enc->state.mb_maps[_mbi][0];
@@ -756,7 +762,7 @@
   ystride=_enc->state.ref_ystride[0];
   frag_buf_offs=_enc->state.frag_buf_offs;
   fragis=_enc->state.mb_maps[_mbi][0];
-  src=_enc->state.ref_frame_data[OC_FRAME_IO];
+  src=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_IO]];
   ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
   offset_y[0]=offset_y[1]=offset_y[2]=-ystride;
   offset_y[3]=offset_y[5]=0;

Modified: experimental/derf/theora-ptalarbvorm/lib/state.c
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/state.c	2010-04-01 11:33:15 UTC (rev 17104)
+++ experimental/derf/theora-ptalarbvorm/lib/state.c	2010-04-01 13:57:23 UTC (rev 17105)
@@ -469,7 +469,7 @@
    unrestricted motion vectors without special casing the boundary.
   If chroma is decimated in either direction, the padding is reduced by a
    factor of 2 on the appropriate sides.
-  _nrefs: The number of reference buffers to init; must be 3 or 4.*/
+  _nrefs: The number of reference buffers to init; must be 3, 4, or 6.*/
 static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
   th_info       *info;
   unsigned char *ref_frame_data;
@@ -489,7 +489,7 @@
   int            vdec;
   int            rfi;
   int            pli;
-  if(_nrefs<3||_nrefs>4)return TH_EINVAL;
+  if(_nrefs<3||_nrefs>6)return TH_EINVAL;
   info=&_state->info;
   /*Compute the image buffer parameters for each plane.*/
   hdec=!(info->pixel_fmt&1);
@@ -579,6 +579,8 @@
   /*Initialize the reference frame indices.*/
   _state->ref_frame_idx[OC_FRAME_GOLD]=
    _state->ref_frame_idx[OC_FRAME_PREV]=
+   _state->ref_frame_idx[OC_FRAME_GOLD_ORIG]=
+   _state->ref_frame_idx[OC_FRAME_PREV_ORIG]=
    _state->ref_frame_idx[OC_FRAME_SELF]=-1;
   _state->ref_frame_idx[OC_FRAME_IO]=_nrefs>3?3:-1;
   return 0;



More information about the commits mailing list