[xiph-commits] r14384 - branches/theora-thusnelda/lib/enc
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Wed Jan 9 05:40:48 PST 2008
Author: xiphmont
Date: 2008-01-09 05:40:47 -0800 (Wed, 09 Jan 2008)
New Revision: 14384
Modified:
branches/theora-thusnelda/lib/enc/codec_internal.h
branches/theora-thusnelda/lib/enc/encode.c
branches/theora-thusnelda/lib/enc/encoder_toplevel.c
branches/theora-thusnelda/lib/enc/mcenc.c
branches/theora-thusnelda/lib/enc/mode.c
Log:
First pass through new MV and mode selection complete. Commit before
trying to build ;-)
Modified: branches/theora-thusnelda/lib/enc/codec_internal.h
===================================================================
--- branches/theora-thusnelda/lib/enc/codec_internal.h 2008-01-09 01:12:49 UTC (rev 14383)
+++ branches/theora-thusnelda/lib/enc/codec_internal.h 2008-01-09 13:40:47 UTC (rev 14384)
@@ -135,8 +135,6 @@
mv_t analysis_mv[3][2]; /* [cur,prev,prev2][frame,golden] */
/*Minimum motion estimation error from the analysis stage.*/
int aerror;
- /*Minimum 4V motion estimation error from the analysis stage.*/
- int aerror4mv;
char coded;
} macroblock_t;
@@ -185,9 +183,6 @@
/* ogg bitpacker for use in packet coding, other API state */
oggpack_buffer *oggbuffer;
-#ifdef LIBOGG2 /* Remember, this is just until we drop libogg1 */
- ogg_buffer_state *oggbufferstate;
-#endif
unsigned char *frame;
unsigned char *recon;
@@ -313,9 +308,7 @@
extern void EncodeData(CP_INSTANCE *cpi);
-extern ogg_uint32_t PickModes(CP_INSTANCE *cpi,
- ogg_uint32_t *InterError,
- ogg_uint32_t *IntraError);
+extern int PickModes(CP_INSTANCE *cpi);
extern void InitFrameInfo(CP_INSTANCE *cpi);
Modified: branches/theora-thusnelda/lib/enc/encode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/encode.c 2008-01-09 01:12:49 UTC (rev 14383)
+++ branches/theora-thusnelda/lib/enc/encode.c 2008-01-09 13:40:47 UTC (rev 14384)
@@ -169,12 +169,12 @@
fi = yuv[B];
if ( cp[fi] ) {
TransformQuantizeBlock( cpi, mp->mode, fi, mp->mv[B] );
- if(cp[fi] && plane == 0)
- mp->coded |= (1<<B);
+ if(!cp[fi] && plane == 0){
+ mp->coded &= ~(1<<B);
+ if(!mp->coded) oc_unset_mode(cpi,mp);
+ }
}
}
- if ( plane == 0 && mp->coded )
- cpi->ModeCount[mp->mode] ++;
}
return 0;
case 2:
@@ -184,17 +184,21 @@
for ( ; mp<mp_end; mp++ ) {
int fi = mp->yuv[plane][0];
if ( cp[fi] ) {
- mv_t mv;
-
- /* Calculate motion vector as the average of the Y plane ones. */
- /* Uncoded members are 0,0 and not special-cased */
- mv.x = mp->mv[0].x + mp->mv[1].x + mp->mv[2].x + mp->mv[3].x;
- mv.y = mp->mv[0].y + mp->mv[1].y + mp->mv[2].y + mp->mv[3].y;
-
- 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);
- TransformQuantizeBlock( cpi, mp->mode, fi, mv );
+ if(mp->mode == CODE_INTER_FOURMV){
+ mv_t mv;
+
+ /* Calculate motion vector as the average of the Y plane ones. */
+ /* Uncoded members are 0,0 and not special-cased */
+ mv.x = mp->mv[0].x + mp->mv[1].x + mp->mv[2].x + mp->mv[3].x;
+ mv.y = mp->mv[0].y + mp->mv[1].y + mp->mv[2].y + mp->mv[3].y;
+
+ 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);
+
+ TransformQuantizeBlock( cpi, mp->mode, fi, mv );
+ }else
+ TransformQuantizeBlock( cpi, mp->mode, fi, mp->mv[0] );
}
}
@@ -300,69 +304,15 @@
static void PackModes (CP_INSTANCE *cpi) {
ogg_uint32_t i,j;
+ ogg_uint32_t BestScheme = cpi->chooser.scheme_list[0];
- unsigned char Mode0[MAX_MODES];
- ogg_int32_t TmpFreq = -1;
- ogg_int32_t TmpIndex = -1;
-
- ogg_uint32_t BestScheme;
- ogg_uint32_t BestSchemeScore;
- ogg_uint32_t modes=0;
-
const ogg_uint32_t *ModeWords;
const ogg_int32_t *ModeBits;
const unsigned char *ModeScheme;
int SB,MB;
oggpack_buffer *opb=cpi->oggbuffer;
- for(i=0;i<MAX_MODES;i++)
- modes+=cpi->ModeCount[i];
- /* Default/ fallback scheme uses MODE_BITS bits per mode entry */
- BestScheme = (MODE_METHODS - 1);
- BestSchemeScore = modes * 3;
- /* Get a bit score for the available predefined schemes. */
- for ( j = 1; j < (MODE_METHODS - 1); j++ ) {
- int SchemeScore = 0;
- const unsigned char *SchemeList = ModeSchemes[j-1];
-
- /* Find the total bits to code using each avaialable scheme */
- for ( i = 0; i < MAX_MODES; i++ )
- SchemeScore += ModeBitLengths[SchemeList[i]] * cpi->ModeCount[i];
-
- /* Is this the best scheme so far ??? */
- if ( SchemeScore < BestSchemeScore ) {
- BestSchemeScore = SchemeScore;
- BestScheme = j;
- }
- }
-
- /* Order the modes from most to least frequent. Store result as
- scheme 0 */
- {
- int SchemeScore = 24;
-
- for ( j = 0; j < MAX_MODES; j++ ) {
- TmpFreq = -1; /* need to re-initialize for each loop */
- /* Find the most frequent */
- for ( i = 0; i < MAX_MODES; i++ ) {
- /* Is this the best scheme so far ??? */
- if ( cpi->ModeCount[i] > TmpFreq ) {
- TmpFreq = cpi->ModeCount[i];
- TmpIndex = i;
- }
- }
- SchemeScore += ModeBitLengths[j] * cpi->ModeCount[TmpIndex];
- cpi->ModeCount[TmpIndex] = -1;
- Mode0[TmpIndex] = j;
- }
-
- if ( SchemeScore < BestSchemeScore ) {
- BestSchemeScore = SchemeScore;
- BestScheme = 0;
- }
- }
-
/* Encode the best scheme. */
oggpackB_write( opb, BestScheme, (ogg_uint32_t)MODE_METHOD_BITS );
@@ -371,9 +321,9 @@
if ( BestScheme == 0 ) {
for ( j = 0; j < MAX_MODES; j++ ){
/* Note that the last two entries are implicit */
- oggpackB_write( opb, Mode0[j], (ogg_uint32_t)MODE_BITS );
+ oggpackB_write( opb, cpi->chooser.scheme0_ranks, (ogg_uint32_t)MODE_BITS );
}
- ModeScheme = Mode0;
+ ModeScheme = cpi->chooser.scheme0_ranks;
ModeWords = ModeBitPatterns;
ModeBits = ModeBitLengths;
}
Modified: branches/theora-thusnelda/lib/enc/encoder_toplevel.c
===================================================================
--- branches/theora-thusnelda/lib/enc/encoder_toplevel.c 2008-01-09 01:12:49 UTC (rev 14383)
+++ branches/theora-thusnelda/lib/enc/encoder_toplevel.c 2008-01-09 13:40:47 UTC (rev 14384)
@@ -26,93 +26,59 @@
#include "dsp.h"
#include "codec_internal.h"
-static void SetupKeyFrame(CP_INSTANCE *cpi) {
- int j;
+static void CompressKeyFrame(CP_INSTANCE *cpi){
+ oggpackB_reset(cpi->oggbuffer);
+ cpi->FrameType = KEY_FRAME;
+
/* code all blocks */
for(j=0;j<cpi->frag_total;j++)
cpi->frag_coded[j]=1;
- /* Set up for a KEY FRAME */
- cpi->FrameType = KEY_FRAME;
-}
-
-static void UpdateFrame(CP_INSTANCE *cpi){
-
- /* 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);
-
+
+ /* still need to go through mode selection to do MV/mode analysis that
+ will be used by subsequent inter frames. Mode will be special-forced to INTRA for each MB. */
+ PickModes(cpi);
+
/* Encode the data. */
EncodeData(cpi);
-
- if ( cpi->FrameType == KEY_FRAME )
- cpi->LastKeyFrame = 1;
-
+
+ cpi->LastKeyFrame = 1;
}
-static void CompressKeyFrame(CP_INSTANCE *cpi){
-
- SetupKeyFrame(cpi);
-
- /* Compress and output the frist frame. */
- PickIntra(cpi);
- UpdateFrame(cpi);
-
-}
-
static int CompressFrame( CP_INSTANCE *cpi ) {
- ogg_uint32_t InterError;
- ogg_uint32_t IntraError;
ogg_uint32_t i;
- ogg_uint32_t KFIndicator = 0;
- int fi = 0;
- for ( i = 0; i < cpi->macro_total; i++) {
- cpi->macro[i].mode = CODE_INTER_NO_MV; /* Default coding mode */
- cpi->macro[i].coded = 0;
- }
+ oggpackB_reset(cpi->oggbuffer);
+ cpi->FrameType = DELTA_FRAME;
- /* Clear down the macro block level mode and MV arrays. */
for ( i = 0; i < cpi->frag_total; i++, fi++ )
- cpi->frag_coded[fi] = 1; /* TEMPORARY */
+ cpi->frag_coded[i] = 1; /* TEMPORARY */
+
+ /* mark as video frame */
+ oggpackB_write(cpi->oggbuffer,0,1);
- /* Default to delta frames. */
- cpi->FrameType = DELTA_FRAME;
+ /* Write out the frame header information including size. */
+ WriteFrameHeader(cpi);
- /* Select modes and motion vectors for each of the blocks : return
- an error score for inter and intra */
- PickModes( cpi, &InterError, &IntraError );
-
- /* decide whether we really should have made this frame a key frame */
- /* forcing out a keyframe if the max interval is up is done at a higher level */
- if( cpi->info.keyframe_auto_p){
- if( ( 2* IntraError < 5 * InterError )
- && ( KFIndicator >= (ogg_uint32_t)
- cpi->info.keyframe_auto_threshold)
- && ( cpi->LastKeyFrame > cpi->info.keyframe_mindistance)
- ){
- CompressKeyFrame(cpi); /* Code a key frame */
- return 0;
- }
-
+ /* Select modes and motion vectors for each of the blocks */
+ if(PickModes( cpi ) && cpi->info.keyframe_auto_p){
+ /* mode analysis thinks this should have been a keyframe; start over and code as a keyframe instead */
+ CompressKeyFrame(cpi); /* Code a key frame */
+ return 0;
}
/* Increment the frames since last key frame count */
cpi->LastKeyFrame++;
-
- /* Proceed with the frame update. */
- UpdateFrame(cpi);
+ /* Encode the data. */
+ EncodeData(cpi);
+
return 0;
}
Modified: branches/theora-thusnelda/lib/enc/mcenc.c
===================================================================
--- branches/theora-thusnelda/lib/enc/mcenc.c 2008-01-09 01:12:49 UTC (rev 14383)
+++ branches/theora-thusnelda/lib/enc/mcenc.c 2008-01-09 13:40:47 UTC (rev 14384)
@@ -414,16 +414,12 @@
_mbi: The macro block index.
_frame: The frame to search, either OC_FRAME_PREV or OC_FRAME_GOLD.
_bmvs: Returns the individual block motion vectors.
- _error: Returns the prediction error for the macro block motion vector.
- _error4mv: Returns sum of the prediction error for the individual block
- motion vectors.*/
+
void oc_mcenc_search(CP_INSTANCE *cpi,
mc_state *_mcenc,
int _mbi,
int _goldenp,
- mv_t *_bmvs,
- int *_error,
- int *_error4mv){
+ mv_t *_bmvs){
/*TODO: customize error function for speed/(quality+size) tradeoff.*/
@@ -549,7 +545,7 @@
/*Final 4-MV search.*/
/*Simply use 1/4 of the macro block set A and B threshold as the
individual block threshold.*/
- if(_bmvs && _error4mv){
+ if(_bmvs){
t2>>=2;
for(bi=0;bi<4;bi++)
if(best_block_err[bi]>t2){
@@ -611,16 +607,20 @@
}
}
- *_error=oc_mcenc_ysad_halfpel_mbrefine(cpi,_mcenc,_mbi,&best_vec,best_err,ref_framei);
- mb->analysis_mv[0][_goldenp]=best_vec;
- if(_bmvs && _error4mv){
- *_error4mv=0;
- for(bi=0;bi<4;bi++){
- (*_error4mv)+=oc_mcenc_ysad_halfpel_brefine(cpi,_mcenc,_mbi,bi,
- &best_block_vec[bi],
- best_block_err[bi],
- _goldenp);
- _bmvs[bi]=best_block_vec[bi];
+ {
+
+ int error=oc_mcenc_ysad_halfpel_mbrefine(cpi,_mcenc,_mbi,&best_vec,best_err,ref_framei);
+ if(!_goldenp) mb->aerror = error;
+ mb->analysis_mv[0][_goldenp]=best_vec;
+
+ if(_bmvs){
+ for(bi=0;bi<4;bi++){
+ oc_mcenc_ysad_halfpel_brefine(cpi,_mcenc,_mbi,bi,
+ &best_block_vec[bi],
+ best_block_err[bi],
+ _goldenp);
+ _bmvs[bi]=best_block_vec[bi];
+ }
}
}
}
Modified: branches/theora-thusnelda/lib/enc/mode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/mode.c 2008-01-09 01:12:49 UTC (rev 14383)
+++ branches/theora-thusnelda/lib/enc/mode.c 2008-01-09 13:40:47 UTC (rev 14384)
@@ -260,150 +260,239 @@
}
}
-static void SetMBMotionVectorsAndMode(CP_INSTANCE *cpi,
- macroblock_t *mp,
- mv_t *mv,
- int mode){
- oc_mode_set(cpi,mp,mode);
- mp->mv[0] = *mv;
- mp->mv[1] = *mv;
- mp->mv[2] = *mv;
- mp->mv[3] = *mv;
-}
-
-static int BIntraSAD420(CP_INSTANCE *cpi, int fi){
+static int BIntraSAD(CP_INSTANCE *cpi, int fi, int plane){
int sad = 0;
- unsigned char *y = frame + cpi->frag_buffer_index[fi];
+ unsigned char *b = cpi->frame + cpi->frag_buffer_index[fi];
ogg_uint32_t acc = 0;
+ int stride = cpi->stride[plane];
int j;
+
for(j=0;j<8;j++){
- acc += y[0];
- acc += y[1];
- acc += y[2];
- acc += y[3];
- acc += y[4];
- acc += y[5];
- acc += y[6];
- acc += y[7];
- y += cpi->stride[0];
+ acc += b[0];
+ acc += b[1];
+ acc += b[2];
+ acc += b[3];
+ acc += b[4];
+ acc += b[5];
+ acc += b[6];
+ acc += b[7];
+ b += stride;
}
- y = frame + cpi->frag_buffer_index[fi];
+ b = cpi->frame + cpi->frag_buffer_index[fi];
for(j=0;j<8;j++){
- sad += abs ((y[0]<<6)-acc);
- sad += abs ((y[1]<<6)-acc);
- sad += abs ((y[2]<<6)-acc);
- sad += abs ((y[3]<<6)-acc);
- sad += abs ((y[4]<<6)-acc);
- sad += abs ((y[5]<<6)-acc);
- sad += abs ((y[6]<<6)-acc);
- sad += abs ((y[7]<<6)-acc);
- y += cpi->stride[0];
+ sad += abs ((b[0]<<6)-acc);
+ sad += abs ((b[1]<<6)-acc);
+ sad += abs ((b[2]<<6)-acc);
+ sad += abs ((b[3]<<6)-acc);
+ sad += abs ((b[4]<<6)-acc);
+ sad += abs ((b[5]<<6)-acc);
+ sad += abs ((b[6]<<6)-acc);
+ sad += abs ((b[7]<<6)-acc);
+ b += stride;
}
return sad;
}
/* equivalent to adding up the abs values of the AC components of a block */
-static int MBIntraSAD420(CP_INSTANCE *cpi, int mbi){
- macroblock_t *mb = &cpi->macro[mbi];
+static int MBIntraCost420(CP_INSTANCE *cpi, int qi, int mbi, int all){
unsigned char *cp = cpi->frag_coded;
- int sad = 0;
+ macroblock_t *mb = &cpi->macro[mbi];
+ int cost=0;
- int fi = mb->yuv[0][0];
- if(cp[fi]) sad += BIntraSAD420(cpi,fi);
+ /* all frags in a macroblock are valid so long as the macroblock itself is valid */
+ if(mbi < cpi->macro_total){
+ if(all || cp[mb->yuv[0][0]])
+ cost += OC_RES_BITRATES[qi][0][OC_MODE_INTRA]
+ [OC_MINI(BIntraSAD(cpi,mb->yuv[0][0],0)>>12,15)];
+ if(all || cp[mb->yuv[0][1]])
+ cost += OC_RES_BITRATES[qi][0][OC_MODE_INTRA]
+ [OC_MINI(BIntraSAD(cpi,mb->yuv[0][1],0)>>12,15)];
+ if(all || cp[mb->yuv[0][2]])
+ cost += OC_RES_BITRATES[qi][0][OC_MODE_INTRA]
+ [OC_MINI(BIntraSAD(cpi,mb->yuv[0][2],0)>>12,15)];
+ if(all || cp[mb->yuv[0][3]])
+ cost += OC_RES_BITRATES[qi][0][OC_MODE_INTRA]
+ [OC_MINI(BIntraSAD(cpi,mb->yuv[0][3],0)>>12,15)];
+
+ if(all || cp[mb->yuv[1][0]])
+ cost += OC_RES_BITRATES[qi][1][OC_MODE_INTRA]
+ [OC_MINI(BIntraSAD(cpi,mb->yuv[1][0],1)>>12,15)];
+ if(all || cp[mb->yuv[2][0]])
+ cost += OC_RES_BITRATES[qi][2][OC_MODE_INTRA]
+ [OC_MINI(BIntraSAD(cpi,mb->yuv[2][0],2)>>12,15)];
+ }
+
+ /* Bit costs are stored in the table with extra precision. Round them down to whole bits.*/
+ return cost + (1<<OC_BIT_SCALE-1) >> OC_BIT_SCALE;
+}
- fi = mb->yuv[0][1];
- if(cp[fi]) sad += BIntraSAD420(cpi,fi);
+static signed char mvmap[2][63] = {
+ { -15,-15,-14, -14,-13,-13,-12, -12,-11,-11,-10, -10, -9, -9, -8,
+ -8, -7, -7, -6, -6, -5, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0,
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15 },
+ { -7, -7, -7, -7, -6, -6, -6, -6, -5, -5, -5, -5, -4, -4, -4,
+ -4, -3, -3, -3, -3, -2, -2, -2, -2, -1, -1, -1, -1, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7 }
+};
- fi = mb->yuv[0][2];
- if(cp[fi]) sad += BIntraSAD420(cpi,fi);
+static signed char mvmap2[2][63] = {
+ { -1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1,
+ 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
+ { -1,-1,-1, 0,-1,-1,-1, 0,-1,-1,-1, 0,-1,-1,-1,
+ 0,-1,-1,-1, 0,-1,-1,-1, 0,-1,-1,-1, 0,-1,-1,-1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }
+};
- fi = mb->yuv[0][3];
- if(cp[fi]) sad += BIntraSAD420(cpi,fi);
-
- fi = mb->yuv[1][0];
- if(cp[fi]) sad += BIntraSAD420(cpi,fi);
-
- fi = mb->yuv[2][0];
- if(cp[fi]) sad += BIntraSAD420(cpi,fi);
-
+static int BInterSAD(CP_INSTANCE *cpi, int fi, int plane, int goldenp, mv_t mv, int qp){
+ int sad = 0;
+ unsigned char *b = cpi->frame + cpi->frag_buffer_index[fi];
+ int mx = mvmap[qp][mv.x+31];
+ int my = mvmap[qp][mv.y+31];
+ int mx2 = mvmap2[qp][mv.x+31];
+ int my2 = mvmap2[qp][mv.y+31];
+ unsigned char *r = (goldenp ? cpi->golden : cpi->recon ) +
+ cpi->frag_buffer_index[fi] + my * stride + mx;
+ int stride = cpi->stride[plane];
+ int j;
+
+ if(mx2 || my2){
+ unsigned char *r2 = r1 + my2 * stride + mx2;
+
+ for(j=0;j<8;j++){
+ sad += abs (b[0]-((r[0]+r2[0])>>1));
+ sad += abs (b[1]-((r[1]+r2[1])>>1));
+ sad += abs (b[2]-((r[2]+r2[2])>>1));
+ sad += abs (b[3]-((r[3]+r2[3])>>1));
+ sad += abs (b[4]-((r[4]+r2[4])>>1));
+ sad += abs (b[5]-((r[5]+r2[5])>>1));
+ sad += abs (b[6]-((r[6]+r2[6])>>1));
+ sad += abs (b[7]-((r[7]+r2[7])>>1));
+ b += stride;
+ }
+
+ }else{
+ for(j=0;j<8;j++){
+ sad += abs (b[0]-r[0]);
+ sad += abs (b[1]-r[1]);
+ sad += abs (b[2]-r[2]);
+ sad += abs (b[3]-r[3]);
+ sad += abs (b[4]-r[4]);
+ sad += abs (b[5]-r[5]);
+ sad += abs (b[6]-r[6]);
+ sad += abs (b[7]-r[7]);
+ b += stride;
+ }
+ }
return sad;
}
-static int InterSad(CP_INSTANCE *cpi, int mbi, mv_t mv){
- macroblock_t *mb = &cpi->macro[mbi];
+static int MBInterCost420(CP_INSTANCE *cpi, int mbi, mv_t mv, int goldenp){
unsigned char *cp = cpi->frag_coded;
- int sad = 0;
- int i;
- for(i=0;i<4;i++){
- int fi = mb->y[i];
- if(cp[fi]){
- unsigned char *y = frame + cpi->frag_buffer_index[fi];
- ogg_uint32_t acc = 0;
- int j;
- for(j=0;j<8;j++){
- acc += y[0];
- acc += y[1];
- acc += y[2];
- acc += y[3];
- acc += y[4];
- acc += y[5];
- acc += y[6];
- acc += y[7];
- y += cpi->stride[0];
- }
+ macroblock_t *mb = &cpi->macro[mbi];
+ int cost = 0;
- y = frame + cpi->frag_buffer_index[fi];
- for(j=0;j<8;j++){
- sad += abs ((y[0]<<6)-acc);
- sad += abs ((y[1]<<6)-acc);
- sad += abs ((y[2]<<6)-acc);
- sad += abs ((y[3]<<6)-acc);
- sad += abs ((y[4]<<6)-acc);
- sad += abs ((y[5]<<6)-acc);
- sad += abs ((y[6]<<6)-acc);
- sad += abs ((y[7]<<6)-acc);
- y += cpi->stride[0];
- }
- }
- }
- return sad;
+ if(cp[mb->yuv[0][0]])
+ cost += OC_RES_BITRATES[qi][0][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[0][0],0,goldenp,mv,0)>>6,15)];
+ if(cp[mb->yuv[0][1]])
+ cost += OC_RES_BITRATES[qi][0][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[0][1],0,goldenp,mv,0)>>6,15)];
+ if(cp[mb->yuv[0][2]])
+ cost += OC_RES_BITRATES[qi][0][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[0][2],0,goldenp,mv,0)>>6,15)];
+ if(cp[mb->yuv[0][3]])
+ cost += OC_RES_BITRATES[qi][0][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[0][3],0,goldenp,mv,0)>>6,15)];
+ if(cp[mb->yuv[1][0]])
+ cost += OC_RES_BITRATES[qi][1][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[1][0],1,goldenp,mv,1)>>6,15)];
+ if(cp[mb->yuv[2][0]])
+ cost += OC_RES_BITRATES[qi][2][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[2][0],2,goldenp,mv,1)>>6,15)];
+ /* Bit costs are stored in the table with extra precision. Round them down to whole bits.*/
+ return cost + (1<<OC_BIT_SCALE-1) >> OC_BIT_SCALE;
+}
+static int MBInter4Cost420(CP_INSTANCE *cpi, int mbi, mv_t mv[4], int goldenp){
+ unsigned char *cp = cpi->frag_coded;
+ macroblock_t *mb = &cpi->macro[mbi];
+ int cost = 0;
+ mv_t ch;
+ if(cp[mb->yuv[0][0]])
+ cost += OC_RES_BITRATES[qi][0][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[0][0],0,goldenp,mv[0],0)>>6,15)];
+ if(cp[mb->yuv[0][1]])
+ cost += OC_RES_BITRATES[qi][0][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[0][1],0,goldenp,mv[1],0)>>6,15)];
+ if(cp[mb->yuv[0][2]])
+ cost += OC_RES_BITRATES[qi][0][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[0][2],0,goldenp,mv[2],0)>>6,15)];
+ if(cp[mb->yuv[0][3]])
+ cost += OC_RES_BITRATES[qi][0][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[0][3],0,goldenp,mv[3],0)>>6,15)];
+ /* Calculate motion vector as the average of the Y plane ones. */
+ /* Uncoded members are 0,0 and not special-cased */
+ ch.x = mv[0].x + mv[1].x + mv[2].x + mv[3].x;
+ ch.y = mv[0].y + mv[1].y + mv[2].y + mv[3].y;
+
+ ch.x = ( ch.x >= 0 ? (ch.x + 2) / 4 : (ch.x - 2) / 4);
+ ch.y = ( ch.y >= 0 ? (ch.y + 2) / 4 : (ch.y - 2) / 4);
+
+ if(cp[mb->yuv[1][0]])
+ cost += OC_RES_BITRATES[qi][1][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[1][0],1,goldenp,ch,1)>>6,15)];
+ if(cp[mb->yuv[2][0]])
+ cost += OC_RES_BITRATES[qi][2][modei]
+ [OC_MINI(BInterSAD(cpi,mb->yuv[2][0],2,goldenp,ch,1)>>6,15)];
+
+ /* Bit costs are stored in the table with extra precision. Round them down to whole bits.*/
+ return cost + (1<<OC_BIT_SCALE-1) >> OC_BIT_SCALE;
}
-ogg_uint32_t PickModes(CP_INSTANCE *cpi,
- ogg_uint32_t *InterError,
- ogg_uint32_t *IntraError) {
+int PickModes(CP_INSTANCE *cpi){
unsigned char qi = cpi->BaseQ; // temporary
-
+ superblock_t *sb = cp->super[0];
+ superblock_t *sb_end = sb + cpi->super_n[0];
mc_state mcenc;
- mv_t bmvs[4];
int mbi, bi;
-
- oc_mode_scheme_chooser_init(cpi);
+ ogg_uint32_t interbits = 0;
+ ogg_uint32_t intrabits = 0;
+
+ mv_t last_mv = {0,0};
+ mv_t prior_mv = {0,0};
+
oc_mcenc_start(cpi, &mcenc);
- *InterError = 0;
- *IntraError = 0;
- cpi->MVBits_0 = 0;
- cpi->MVBits_1 = 0;
-
- /* Scan through macroblocks. */
for(mbi = 0; mbi<cpi->macro_total; mbi++){
- ogg_uint32_t sad[8] = {0,0,0,0, 0,0,0,0};
macroblock_t *mb = &cp->macro[mbi];
/*Move the motion vector predictors back a frame */
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 */
- oc_mcenc_search(cpi, &mcenc, mbi, 0, bmvs, &errormv, &error4mv);
+ oc_mcenc_search(cpi, &mcenc, mbi, 0, mb->mv);
+ /* replace the block MVs for not-coded blocks with (0,0).*/
+ mb->coded = 0;
+ for ( bi=0; bi<4; bi++ ){
+ fi = mbp->yuv[0][bi];
+ if(!cp[fi])
+ mb->mv[fi]={0,0};
+ else
+ mb->coded |= (1<<B);
+ }
+
if(mb->coded==0){
/* Don't bother to do a MV search against the golden frame.
Just re-use the last vector, which should match well since the
@@ -413,258 +502,167 @@
}
/* search golden frame */
- oc_mcenc_search(cpi, &mcenc, mbi, 1, NULL, &errormv_gold, NULL);
+ oc_mcenc_search(cpi, &mcenc, mbi, 1, NULL);
+ }
+
+ oc_mode_scheme_chooser_init(cpi);
+ cpi->MVBits_0 = 0;
+ cpi->MVBits_1 = 0;
+
+ /* Choose modes; must be done in Hilbert order */
+ for(; sb<sb_end; sb++){
+ for(mbi = 0; mbi<4; mbi++){ /* mode addressing is through Y plane, always 4 MB per SB */
+ ogg_uint32_t cost[8] = {0,0,0,0, 0,0,0,0};
+ macroblock_t *mb = sb->m[mbi];
- if(cpi->FrameType == KEY_FRAME){
- mb->mode = CODE_INTRA;
- continue;
- }
+ if(cpi->FrameType == KEY_FRAME){
+ mb->mode = CODE_INTRA;
+ continue;
+ }
- /* Count the number of coded blocks that are luma blocks, and replace the
- block MVs for not-coded blocks with (0,0).*/
- for ( bi=0; bi<4; bi++ ){
- fi = mbp->yuv[0][bi];
- if(!cp[fi]) bmvs[bi]={0,0};
- }
-
- /**************************************************************
- Find the block choice with the lowest estimated coding cost
+ /**************************************************************
+ Find the block choice with the lowest estimated coding cost
- NOTE THAT if U or V is coded but no Y from a macro block then the
- mode will be CODE_INTER_NO_MV as this is the default state to
- which the mode data structure is initialised in encoder and
- decoder at the start of each frame. */
+ NOTE THAT if U or V is coded but no Y from a macro block then
+ the mode will be CODE_INTER_NO_MV as this is the default
+ state to which the mode data structure is initialised in
+ encoder and decoder at the start of each frame. */
- /* calculate INTRA error */
- for(ci=1;ci<64;ci++)
- sad[CODE_INTRA]+=abs(efrag->dct_coeffs[ci]);
-
+ /* block coding cost is estimated from correlated SAD metrics */
+ cost[CODE_INTER_NO_MV] = MBInterCost420(cpi,mbi,(mv_t){0,0},0);
- BestError = HUGE_ERROR;
-
-
- /* Look at the intra coding error. */
- MBIntraError = GetMBIntraError( cpi, mbp );
- BestError = (BestError > MBIntraError) ? MBIntraError : BestError;
-
- /* Get the golden frame error */
- MBGFError = GetMBInterError( cpi, cpi->frame, cpi->golden,
- mbp, 0, 0 );
- BestError = (BestError > MBGFError) ? MBGFError : BestError;
-
- /* Calculate the 0,0 case. */
- MBInterError = GetMBInterError( cpi, cpi->frame,
- cpi->lastrecon,
- mbp, 0, 0 );
- BestError = (BestError > MBInterError) ? MBInterError : BestError;
-
- /* Measure error for last MV */
- MBLastInterError = GetMBInterError( cpi, cpi->frame,
- cpi->lastrecon,
- mbp, LastInterMVect.x,
- LastInterMVect.y );
- BestError = (BestError > MBLastInterError) ?
- MBLastInterError : BestError;
-
- /* Measure error for prior last MV */
- MBPriorLastInterError = GetMBInterError( cpi, cpi->frame,
- cpi->lastrecon,
- mbp, PriorLastInterMVect.x,
- PriorLastInterMVect.y );
- BestError = (BestError > MBPriorLastInterError) ?
- MBPriorLastInterError : BestError;
+ /* 'should this have been a keyframe in retrospect' tracking;
+ includes none of the rest of the inter-style labelling and
+ flagging overhead, but must count 'uncoded' frags within the
+ frame */
+ intrabits += MBIntraCost420(cpi,mbi,1);
- /* Temporarily force usage of no motionvector blocks */
- MBInterMVError = HUGE_ERROR;
- InterMVect.x = 0; /* Set 0,0 motion vector */
- InterMVect.y = 0;
+ if(mb->coded == 0){
- /* If the best error is above the required threshold search
- for a new inter MV */
- if ( BestError > cpi->MinImprovementForNewMV && cpi->MotionCompensation) {
- /* Use a mix of heirachical and exhaustive searches for
- quick mode. */
- if ( cpi->info.quick_p ) {
- MBInterMVError = GetMBMVInterError( cpi, cpi->lastrecon,
- mbp,
- cpi->MVPixelOffsetY,
- &InterMVect );
+ mb->mode = CODE_INTER_NO_MV;
- /* If we still do not have a good match try an exhaustive
- MBMV search */
- if ( (MBInterMVError > cpi->ExhaustiveSearchThresh) &&
- (BestError > cpi->ExhaustiveSearchThresh) ) {
-
- MBInterMVExError =
- GetMBMVExhaustiveSearch( cpi, cpi->lastrecon,
- mbp,
- &InterMVectEx );
-
- /* Is the Variance measure for the EX search
- better... If so then use it. */
- if ( MBInterMVExError < MBInterMVError ) {
- MBInterMVError = MBInterMVExError;
- InterMVect.x = InterMVectEx.x;
- InterMVect.y = InterMVectEx.y;
- }
- }
- }else{
- /* Use an exhaustive search */
- MBInterMVError =
- GetMBMVExhaustiveSearch( cpi, cpi->lastrecon,
- mbp,
- &InterMVect );
+ }else{
+
+ cost[CODE_INTRA] = MBIntraCost420(cpi,mbi,0);
+ cost[CODE_INTER_PLUS_MV] = MBInterError420(cpi,mbi,mb->analysis_mv[0][0],0);
+ cost[CODE_INTER_LAST_MV] = MBInterError420(cpi,mbi,last_mv,0);
+ cost[CODE_INTER_PRIOR_LAST] = MBInterError420(cpi,mbi,prior_mv,0);
+ cost[CODE_USING_GOLDEN] = MBInterError420(cpi,mbi,(mv_t){0,0},1);
+ cost[CODE_GOLDEN_MV] = MBInterError420(cpi,mbi,mb->analysis_mv[0][1],0);
+ cost[CODE_INTER_FOURMV] = MBInter4Error420(cpi,mbi,mb->mv,0);
+
+ /* add estimated labelling cost for each mode */
+ for(mode = 0; mode < 8; mode++)
+ cost[mode] += oc_mode_cost(&cpi->chooser,mode);
+
+ /* Add the motion vector bits for each mode that requires them.*/
+ mb_mv_bits_0 = MvBits[mb->analysis_mv[0][0].x] + MvBits[mb->analysis_mv[0][0].y];
+ mb_gmv_bits_0 = MvBits[mb->analysis_mv[0][1].x] + MvBits[mb->analysis_mv[0][1].y];
+ mb_4mv_bits_0 = mb_4mv_bits_1 = 0;
+ if(mb->coded & 1){
+ mb_4mv_bits_0 += MvBits[mb->mv[0].x] + MvBits[mb->mv[0].y];
+ mb_4mv_bits_1 += 12;
}
-
-
- /* Is the improvement, if any, good enough to justify a new MV */
- if ( (16 * MBInterMVError < (BestError * cpi->MVChangeFactor)) &&
- ((MBInterMVError + cpi->MinImprovementForNewMV) < BestError) ){
- BestError = MBInterMVError;
+ if(mb->coded & 2){
+ mb_4mv_bits_0 += MvBits[mb->mv[1].x] + MvBits[mb->mv[1].y];
+ mb_4mv_bits_1 += 12;
}
-
- }
-
- /* If the best error is still above the required threshold
- search for a golden frame MV */
- MBGF_MVError = HUGE_ERROR;
- GFMVect.x = 0; /* Set 0,0 motion vector */
- GFMVect.y = 0;
- if ( BestError > cpi->MinImprovementForNewMV && cpi->MotionCompensation) {
- /* Do an MV search in the golden reference frame */
- MBGF_MVError = GetMBMVInterError( cpi, cpi->golden,
- mbp,
- cpi->MVPixelOffsetY, &GFMVect );
-
- /* Measure error for last GFMV */
- LastMBGF_MVError = GetMBInterError( cpi, cpi->frame,
- cpi->golden,
- mbp,
- LastGFMVect.x,
- LastGFMVect.y );
-
- /* Check against last GF motion vector and reset if the
- search has thrown a worse result. */
- if ( LastMBGF_MVError < MBGF_MVError ) {
- GFMVect.x = LastGFMVect.x;
- GFMVect.y = LastGFMVect.y;
- MBGF_MVError = LastMBGF_MVError;
- }else{
- LastGFMVect.x = GFMVect.x;
- LastGFMVect.y = GFMVect.y;
+ if(mb->coded & 4){
+ mb_4mv_bits_0 += MvBits[mb->mv[2].x] + MvBits[mb->mv[2].y];
+ mb_4mv_bits_1 += 12;
}
-
- /* Is the improvement, if any, good enough to justify a new MV */
- if ( (16 * MBGF_MVError < (BestError * cpi->MVChangeFactor)) &&
- ((MBGF_MVError + cpi->MinImprovementForNewMV) < BestError) ) {
- BestError = MBGF_MVError;
+ if(mb->coded & 8){
+ mb_4mv_bits_0 += MvBits[mb->mv[3].x] + MvBits[mb->mv[3].y];
+ mb_4mv_bits_1 += 12;
}
+
+ /* We use the same opportunity cost method of estimating the
+ cost of coding the motion vectors with the two different
+ schemes as we do for estimating the cost of the mode
+ labels. However, because there are only two schemes and
+ they're both pretty simple, this can just be done inline.*/
+ cost[CODE_INTER_MV] +=
+ OC_MINI(cp->MVBits_0 + mb_mv_bits_0, cp->MVBits_1+12)-
+ OC_MINI(cp->MVBits_0, cp->MVBits_1);
+ cost[CODE_GOLDEN_MV] +=
+ OC_MINI(cp->MVBits_0 + mb_gmv_bits_0, cp->MVBits_1+12)-
+ OC_MINI(cp->MVBits_0, cp->MVBits_1);
+ cost[CODE_INTER_FOURMV] +=
+ OC_MINI(cp->MVBits_0 + mb_4mv_bits_0, cp->MVBits_1 + mb_4mv_bits_1)-
+ OC_MINI(cp->MVBits_0, cp->MVBits_1);
+
+ /* Finally, pick the mode with the cheapest estimated bit cost.*/
+ mode=0;
+ for(i=1;i<8;i++)
+ if(cost[i]<cost[mode])
+ mode=i;
}
- /* Finally... If the best error is still to high then consider
- the 4MV mode */
- MBInterFOURMVError = HUGE_ERROR;
- if ( BestError > cpi->FourMVThreshold && cpi->MotionCompensation) {
- /* Get the 4MV error. */
- MBInterFOURMVError =
- GetFOURMVExhaustiveSearch( cpi, cpi->lastrecon,
- mbp,
- FourMVect );
+ oc_mode_set(cpi,mb,mode);
+ interbits += cost[mode];
- /* If the improvement is great enough then use the four MV mode */
- if ( ((MBInterFOURMVError + cpi->MinImprovementForFourMV) <
- BestError) && (16 * MBInterFOURMVError <
- (BestError * cpi->FourMvChangeFactor))) {
- BestError = MBInterFOURMVError;
- }
+ switch(mode){
+ case CODE_INTER_MV:
+ cpi->MVBits_0 += mb_mv_bits_0;
+ cpi->MVBits_1 += 12;
+ prior_mv = last_mav;
+ last_mv = mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = mb->analysis_mv[0][0];
+ break;
+ case OC_MODE_INTER_MV_LAST:
+ mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = last_mv;
+ mb->mv = last_mv;
+ break;
+ case OC_MODE_INTER_MV_LAST2:
+ 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 OC_MODE_INTER_MV_FOUR:
+ 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 OC_MODE_GOLDEN_MV:
+ cpi->MVBits_0 += mb_gmv_bits_0;
+ cpi->MVBits_1 += 12;
+ mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = mb->analysis_mv[0][1];
+ break;
+ default:
+ mb->mv[0] = mb->mv[1] = mb->mv[2] = mb->mv[3] = (mv_t){0,0};
+ break;
}
+ }
+ }
- /********************************************************
- end finding the best error
- *******************************************************
+ if(cpi->FrameType != KEY_FRAME){
- Figure out what to do with the block we chose
+ if(interbits>intrabits) return 1; /* short circuit */
- Over-ride and force intra if error high and Intra error similar
- Now choose a mode based on lowest error (with bias towards no MV) */
+ /* finish adding flagging overhead costs to inter bit counts */
+
+ if(cpi->MVBits_0 < cpi->MVBits_1)
+ interbits += cpi->MVBits_0;
+ else
+ interbits += cpi->MVBits_1;
+
+ interbits+=cpi->chooser.scheme_bits[cpi->chooser.scheme_list[0]];
+
+ if(interbits>intrabits) return 1; /* short circuit */
- if ( (BestError > cpi->InterTripOutThresh) &&
- (10 * BestError > MBIntraError * 7 ) ) {
- SetMBMotionVectorsAndMode(cpi,mbp,&ZeroVect,CODE_INTRA);
- } else if ( BestError == MBInterError ) {
- SetMBMotionVectorsAndMode(cpi,mbp,&ZeroVect,CODE_INTER_NO_MV);
- } else if ( BestError == MBGFError ) {
- SetMBMotionVectorsAndMode(cpi,mbp,&ZeroVect,CODE_USING_GOLDEN);
- } else if ( BestError == MBLastInterError ) {
- SetMBMotionVectorsAndMode(cpi,mbp,&LastInterMVect,CODE_INTER_LAST_MV);
- } else if ( BestError == MBPriorLastInterError ) {
- SetMBMotionVectorsAndMode(cpi,mbp,&PriorLastInterMVect,CODE_INTER_PRIOR_LAST);
-
- /* Swap the prior and last MV cases over */
- TmpMVect = PriorLastInterMVect;
- PriorLastInterMVect = LastInterMVect;
- LastInterMVect = TmpMVect;
-
- } else if ( BestError == MBInterMVError ) {
-
- SetMBMotionVectorsAndMode(cpi,mbp,&InterMVect,CODE_INTER_PLUS_MV);
-
- /* Update Prior last mv with last mv */
- PriorLastInterMVect.x = LastInterMVect.x;
- PriorLastInterMVect.y = LastInterMVect.y;
-
- /* Note last inter MV for future use */
- LastInterMVect.x = InterMVect.x;
- LastInterMVect.y = InterMVect.y;
-
- CountMotionVector( cpi, &InterMVect);
-
- } else if ( BestError == MBGF_MVError ) {
-
- SetMBMotionVectorsAndMode(cpi,mbp,&GFMVect,CODE_GOLDEN_MV);
-
- /* Note last inter GF MV for future use */
- LastGFMVect.x = GFMVect.x;
- LastGFMVect.y = GFMVect.y;
-
- CountMotionVector( cpi, &GFMVect);
- } else if ( BestError == MBInterFOURMVError ) {
-
- mbp->mode = CODE_INTER_FOURMV;
- mbp->mv[0] = FourMVect[0];
- mbp->mv[1] = FourMVect[1];
- mbp->mv[2] = FourMVect[2];
- mbp->mv[3] = FourMVect[3];
-
- /* Note the four MVs values for current macro-block. */
- CountMotionVector( cpi, &FourMVect[0]);
- CountMotionVector( cpi, &FourMVect[1]);
- CountMotionVector( cpi, &FourMVect[2]);
- CountMotionVector( cpi, &FourMVect[3]);
-
- /* Update Prior last mv with last mv */
- PriorLastInterMVect = LastInterMVect;
-
- /* Note last inter MV for future use */
- LastInterMVect = FourMVect[3];
-
- } else {
-
- SetMBMotionVectorsAndMode(cpi, mbp,&ZeroVect,CODE_INTRA);
-
- }
-
- /* setting up mode specific block types
- *******************************************************/
-
- *InterError += (BestError>>8);
- *IntraError += (MBIntraError>>8);
-
+ /* The easiest way to count the bits needed for coded/not coded fragments is
+ to code them. */
+ {
+ ogg_uint32_t bits = oggpackB_bits(cpi->oggpack_buffer);
+ PackAndWriteDFArray(cpi);
+ interbits += oggpackB_bits(cpi->oggpack_buffer) - bits;
}
+
+ if(interbits>intrabits) return 1;
+
}
- /* Return number of pixels coded */
return 0;
}
More information about the commits
mailing list