[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