Commit 9daf3154 authored by Adrian Grange's avatar Adrian Grange Committed by Paul Wilkins

Superblock encoding order

This is the first patch to add superblock (32x32) coding
order capabilities. It does not yet do any mode selection
at the SB level, that will follow in a further patch.

This patch encodes rows of SBs rather than
MBs, each SB contains 2x2 MBs.

Two intra prediction modes have been disabled since they
require reconstructed data for the above-right MB which
may not have been encoded yet (e.g. for the bottom right
MB in each SB).

Results on the one test clip I have tried (720p GIPS clip)
suggest that it is somewhere around 0.2dB worse than the
baseline version, so there may be bugs.

It has been tested with no experiments enabled and with
the following 3 experiments enabled:
  --enable-enhanced_interp
  --enable-high_precision_mv
  --enable-sixteenth_subpel_uv
in each case the decode buffer matches the recon buffer
(using "cmp" to compare the dumped/decoded frames).
Note: Testing these experiments individually created
errors.

Some problems were found with other experiments but it
is unclear what state these experiments are in:
  --enable-comp_intra_pred
  --enable-newentropy
  --enable-uvintra

This code has not been extensively tested yet, so there
is every likelihood that further bugs remain. I also
intend to do some code cleanup & refactoring in tandem
with the next patch that adds the 32x32 modes.

Change-Id: I1eba7f740a70b3510df58db53464535ef881b4d9
parent 78ecbc98
......@@ -224,6 +224,7 @@ EXPERIMENT_LIST="
sixteenth_subpel_uv
comp_intra_pred
newentropy
superblocks
"
CONFIG_LIST="
external_build
......
......@@ -337,6 +337,9 @@ typedef struct MacroBlockD
#if CONFIG_RUNTIME_CPU_DETECT
struct VP8_COMMON_RTCD *rtcd;
#endif
int mb_index; // Index of the MB in the SB (0..3)
} MACROBLOCKD;
......
......@@ -81,7 +81,7 @@ void vp8_find_near_mvs
else
cnt[CNT_INTRA] += 2;
}
/* Process above left or the one frome last frame */
/* Process above left or the one from last frame */
if ( aboveleft->mbmi.ref_frame != INTRA_FRAME||
(lf_here->mbmi.ref_frame==LAST_FRAME && refframe == LAST_FRAME))
{
......
......@@ -666,7 +666,6 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
const int mis = pbi->common.mode_info_stride;
MACROBLOCKD *const xd = & pbi->mb;
int index = mb_row * pbi->common.mb_cols + mb_col;
int_mv *const mv = & mbmi->mv;
int mb_to_left_edge;
int mb_to_right_edge;
......@@ -1017,91 +1016,75 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
void vp8_decode_mode_mvs(VP8D_COMP *pbi)
{
MODE_INFO *mi = pbi->common.mi;
MODE_INFO *prev_mi = pbi->common.prev_mi;
int i;
VP8_COMMON *cm = &pbi->common;
MODE_INFO *mi = cm->mi;
int sb_row, sb_col;
int sb_rows = (cm->mb_rows + 1)>>1;
int sb_cols = (cm->mb_cols + 1)>>1;
int row_delta[4] = { 0, +1, 0, -1};
int col_delta[4] = {+1, -1, +1, +1};
int mb_row = -1;
#if 0
FILE *statsfile;
statsfile = fopen("decsegmap.stt", "a");
fprintf(statsfile, "\n" );
#endif
MODE_INFO *prev_mi = cm->prev_mi;
mb_mode_mv_init(pbi);
#if CONFIG_QIMODE
if(pbi->common.frame_type==KEY_FRAME && !pbi->common.kf_ymode_probs_update)
if(cm->frame_type==KEY_FRAME && !cm->kf_ymode_probs_update)
{
pbi->common.kf_ymode_probs_index = vp8_read_literal(&pbi->bc, 3);
cm->kf_ymode_probs_index = vp8_read_literal(&pbi->bc, 3);
}
#endif
while (++mb_row < pbi->common.mb_rows)
for (sb_row=0; sb_row<sb_rows; sb_row++)
{
int mb_col = -1;
int mb_to_top_edge;
int mb_to_bottom_edge;
pbi->mb.mb_to_top_edge =
mb_to_top_edge = -((mb_row * 16)) << 3;
mb_to_top_edge -= LEFT_TOP_MARGIN;
pbi->mb.mb_to_bottom_edge =
mb_to_bottom_edge = ((pbi->common.mb_rows - 1 - mb_row) * 16) << 3;
mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN;
int mb_col = 0;
int mb_row = (sb_row <<1);
#if 0
fprintf(statsfile, "\n" );
#endif
while (++mb_col < pbi->common.mb_cols)
for (sb_col=0; sb_col<sb_cols; sb_col++)
{
/*read_mb_modes_mv(pbi, xd->mode_info_context, &xd->mode_info_context->mbmi, mb_row, mb_col);*/
if(pbi->common.frame_type == KEY_FRAME)
{
//printf("<%d %d> \n", mb_row, mb_col);
vp8_kfread_modes(pbi, mi, mb_row, mb_col);
}
else
for ( i=0; i<4; i++ )
{
read_mb_modes_mv(pbi, mi, &mi->mbmi,
prev_mi,
mb_row, mb_col);
}
int mb_to_top_edge;
int mb_to_bottom_edge;
//printf("%3d", mi->mbmi.mode);
int dy = row_delta[i];
int dx = col_delta[i];
int offset_extended = dy * cm->mode_info_stride + dx;
/*
if(pbi->common.current_video_frame==7)
{
FILE *fmode=fopen("kfmode.txt", "a");
fprintf(fmode, "%3d:%3d:%d\n",mb_row, mb_col, mi->mbmi.mode);
fclose(fmode);
if ((mb_row >= cm->mb_rows) || (mb_col >= cm->mb_cols))
{
/* next macroblock */
mb_row += dy;
mb_col += dx;
mi += offset_extended;
prev_mi += offset_extended;
continue;
}
}*/
/*
if(mi->mbmi.mode==I8X8_PRED)
{
printf("F%3d:%d:%d\n", pbi->common.current_video_frame, mb_row, mb_col);
}
*/
#if 0
fprintf(statsfile, "%2d%2d%2d ",
mi->mbmi.segment_id, mi->mbmi.ref_frame, mi->mbmi.mode );
#endif
prev_mi++;
mi++; /* next macroblock */
}
// printf("\n");
prev_mi++;
mi++; /* skip left predictor each row */
}
pbi->mb.mb_to_top_edge = mb_to_top_edge = -((mb_row * 16)) << 3;
mb_to_top_edge -= LEFT_TOP_MARGIN;
#if 0
fclose(statsfile);
#endif
pbi->mb.mb_to_bottom_edge =
mb_to_bottom_edge =
((pbi->common.mb_rows - 1 - mb_row) * 16) << 3;
mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN;
if(cm->frame_type == KEY_FRAME)
vp8_kfread_modes(pbi, mi, mb_row, mb_col);
else
read_mb_modes_mv(pbi, mi, &mi->mbmi, prev_mi, mb_row,
mb_col);
/* next macroblock */
mb_row += dy;
mb_col += dx;
mi += offset_extended;
prev_mi += offset_extended;
}
}
mi += cm->mode_info_stride + (1 - (cm->mb_cols & 0x1));
prev_mi += cm->mode_info_stride + (1 - (cm->mb_cols & 0x1));
}
}
This diff is collapsed.
......@@ -477,7 +477,8 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
}
#if CONFIG_DEBUG
vp8_recon_write_yuv_frame("recon.yuv", cm->frame_to_show);
if(cm->show_frame)
vp8_recon_write_yuv_frame("recon.yuv", cm->frame_to_show);
#endif
vp8_clear_system_state();
......
This diff is collapsed.
......@@ -61,14 +61,31 @@ typedef struct
} bmi[16];
} PARTITION_INFO;
// Structure to hold snapshot of coding context during the mode picking process
// TODO Do we need all of these?
typedef struct
{
DECLARE_ALIGNED(16, short, src_diff[400]); // 16x16 Y 8x8 U 8x8 V 4x4 2nd Y
MODE_INFO mic;
PARTITION_INFO partition_info;
int_mv best_ref_mv;
int rate;
int distortion;
int intra_error;
int best_mode_index;
int rddiv;
int rdmult;
} PICK_MODE_CONTEXT;
typedef struct
{
DECLARE_ALIGNED(16, short, src_diff[400]); // 16x16 Y 8x8 U 8x8 V 4x4 2nd Y
DECLARE_ALIGNED(16, short, coeff[400]); // 16x16 Y 8x8 U 8x8 V 4x4 2nd Y
DECLARE_ALIGNED(16, unsigned char, thismb[256]);
DECLARE_ALIGNED(16, unsigned char, thismb[256]); // 16x16 Y
unsigned char *thismb_ptr;
// 16 Y blocks, 4 U blocks, 4 V blocks, 1 DC 2nd order block each with 16 entries
// 16 Y blocks, 4 U blocks, 4 V blocks,
// 1 DC 2nd order block each with 16 entries
BLOCK block[25];
YV12_BUFFER_CONFIG src;
......@@ -113,7 +130,6 @@ typedef struct
int mv_row_min;
int mv_row_max;
int vector_range; // Used to monitor limiting range of recent vectors to guide search.
int skip;
int encode_breakout;
......@@ -135,6 +151,16 @@ typedef struct
int optimize;
int q_index;
int encode_as_sb;
// Structure to hold context for each of the 4 MBs within a SB:
// when encoded as 4 independent MBs:
PICK_MODE_CONTEXT mb_context[4];
#if CONFIG_SUPERBLOCKS
// when 4 MBs share coding parameters:
PICK_MODE_CONTEXT sb_context[4];
#endif
void (*vp8_short_fdct4x4)(short *input, short *output, int pitch);
void (*vp8_short_fdct8x4)(short *input, short *output, int pitch);
void (*short_walsh4x4)(short *input, short *output, int pitch);
......
This diff is collapsed.
......@@ -101,7 +101,10 @@ void vp8_encode_intra4x4mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *mb)
int i;
MACROBLOCKD *x = &mb->e_mbd;
#if 0
// Intra modes requiring top-right MB reconstructed data have been disabled
vp8_intra_prediction_down_copy(x);
#endif
for (i = 0; i < 16; i++)
vp8_encode_intra4x4block(rtcd, mb, i);
......
......@@ -911,7 +911,7 @@ static double calc_correction_factor( double err_per_mb,
// PGW TODO..
// This code removes direct dependency on QIndex to determin the range
// (now uses the actual quantizer) but has not been tuned.
static double adjust_maxq_qrange(VP8_COMP *cpi)
static void adjust_maxq_qrange(VP8_COMP *cpi)
{
int i;
double q;
......
......@@ -109,7 +109,7 @@ static unsigned int do_16x16_motion_iteration
//VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
best_err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
(xd->dst.y_buffer, xd->dst.y_stride,
xd->predictor, 16, &best_err);
xd->predictor, 16, best_err);
/* restore UMV window */
x->mv_col_min = tmp_col_min;
......@@ -158,7 +158,7 @@ static int do_16x16_motion_search
err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
(ref->y_buffer + mb_y_offset,
ref->y_stride, xd->dst.y_buffer,
xd->dst.y_stride, &err);
xd->dst.y_stride, INT_MAX);
dst_mv->as_int = 0;
// Test last reference frame using the previous best mv as the
......@@ -224,7 +224,7 @@ static int do_16x16_zerozero_search
err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
(ref->y_buffer + mb_y_offset,
ref->y_stride, xd->dst.y_buffer,
xd->dst.y_stride, &err);
xd->dst.y_stride, INT_MAX);
dst_mv->as_int = 0;
......@@ -255,7 +255,7 @@ static int find_best_16x16_intra
err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
(xd->predictor, 16,
buf->y_buffer + mb_y_offset,
buf->y_stride, &err);
buf->y_stride, err);
// find best
if (err < best_err)
{
......
......@@ -1257,7 +1257,6 @@ int vp8_hex_search
int k = -1;
int all_in;
int best_site = -1;
MACROBLOCKD *xd = &x->e_mbd;
int_mv fcenter_mv;
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
......
......@@ -205,8 +205,7 @@ int calculate_minq_index( double maxq,
if ( minqtarget <= vp8_convert_qindex_to_q(i) )
return i;
}
if ( i == QINDEX_RANGE )
return QINDEX_RANGE-1;
return QINDEX_RANGE-1;
}
void init_minq_luts()
{
......@@ -408,7 +407,6 @@ static int compute_qdelta( VP8_COMP *cpi, double qstart, double qtarget )
int i;
int start_index = cpi->worst_quality;
int target_index = cpi->worst_quality;
int retval = 0;
// Convert the average q value to an index.
for ( i = cpi->best_quality; i < cpi->worst_quality; i++ )
......@@ -590,7 +588,7 @@ static void init_seg_features(VP8_COMP *cpi)
// All other frames.
else
{
// No updeates.. leave things as they are.
// No updates.. leave things as they are.
xd->update_mb_segmentation_map = 0;
xd->update_mb_segmentation_data = 0;
}
......@@ -665,8 +663,6 @@ void vp8_set_speed_features(VP8_COMP *cpi)
cpi->mode_chosen_counts[i] = 0;
}
cpi->mbs_tested_so_far = 0;
// best quality defaults
sf->RD = 1;
sf->search_method = NSTEP;
......@@ -2500,6 +2496,30 @@ static void Pass1Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest,
vp8_set_quantizer(cpi, find_fp_qindex());
vp8_first_pass(cpi);
}
#if 1
void write_yuv_frame_to_file(YV12_BUFFER_CONFIG *frame)
{
// write the frame
int i;
char filename[255];
FILE *fp = fopen("encode_recon.yuv", "a");
for (i = 0; i < frame->y_height; i++)
fwrite(frame->y_buffer + i * frame->y_stride,
frame->y_width, 1, fp);
for (i = 0; i < frame->uv_height; i++)
fwrite(frame->u_buffer + i * frame->uv_stride,
frame->uv_width, 1, fp);
for (i = 0; i < frame->uv_height; i++)
fwrite(frame->v_buffer + i * frame->uv_stride,
frame->uv_width, 1, fp);
fclose(fp);
}
#endif
//#define WRITE_RECON_BUFFER 1
#if WRITE_RECON_BUFFER
void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
......@@ -2567,7 +2587,7 @@ static double compute_edge_pixel_proportion(YV12_BUFFER_CONFIG *frame)
return (double)num_edge_pels/(double)num_pels;
}
// Function to test for conditions that indeicate we should loop
// Function to test for conditions that indicate we should loop
// back and recode a frame.
static BOOL recode_loop_test( VP8_COMP *cpi,
int high_limit, int low_limit,
......@@ -3563,9 +3583,12 @@ static void encode_frame_to_data_rate
loopfilter_frame(cpi, cm);
}
if(cm->show_frame)
write_yuv_frame_to_file(cm->frame_to_show);
update_reference_frames(cm);
// Work out the segment probabilites if segmentation is enabled and
// Work out the segment probabilities if segmentation is enabled and
// the map is due to be updated
if (xd->segmentation_enabled && xd->update_mb_segmentation_map)
{
......@@ -3935,22 +3958,25 @@ static void check_gf_quality(VP8_COMP *cpi)
// Low use of gf
if ((gf_active_pct < 10) || ((gf_active_pct + gf_ref_usage_pct) < 15))
{
// ...but last frame zero zero usage is reasonbable so a new gf might be appropriate
// ...but last frame zero zero usage is reasonable
// so a new gf might be appropriate
if (last_ref_zz_useage >= 25)
{
cpi->gf_bad_count ++;
if (cpi->gf_bad_count >= 8) // Check that the condition is stable
// Check that the condition is stable
if (cpi->gf_bad_count >= 8)
{
cpi->gf_update_recommended = 1;
cpi->gf_bad_count = 0;
}
}
else
cpi->gf_bad_count = 0; // Restart count as the background is not stable enough
cpi->gf_bad_count = 0; // Restart count as the background
// is not stable enough
}
else
cpi->gf_bad_count = 0; // Gf useage has picked up so reset count
cpi->gf_bad_count = 0; // Gf usage has picked up so reset count
}
}
// If the signal is set but has not been read should we cancel it.
......
......@@ -348,7 +348,6 @@ typedef struct VP8_COMP
unsigned int mode_check_freq[MAX_MODES];
unsigned int mode_test_hit_counts[MAX_MODES];
unsigned int mode_chosen_counts[MAX_MODES];
unsigned int mbs_tested_so_far;
int rd_thresh_mult[MAX_MODES];
int rd_baseline_thresh[MAX_MODES];
......@@ -642,9 +641,17 @@ typedef struct VP8_COMP
int *lf_ref_frame_sign_bias;
int *lf_ref_frame;
int force_next_frame_intra; /* force next frame to intra when kf_auto says so */
/* force next frame to intra when kf_auto says so */
int force_next_frame_intra;
int droppable;
// Global store for SB left contexts, one for each MB row in the SB
ENTROPY_CONTEXT_PLANES left_context[2];
// TODO Do we still need this??
int update_context;
} VP8_COMP;
void control_data_rate(VP8_COMP *cpi);
......
This diff is collapsed.
......@@ -19,7 +19,7 @@ extern void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue);
extern void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset,
int *returnrate, int *returndistortion, int *returnintra,
int *best_single_rd_diff, int *best_comp_rd_diff, int *best_hybrid_rd_diff);
extern void vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate);
extern int vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x);
extern void vp8_mv_pred
(
......
......@@ -1460,7 +1460,7 @@ static void show_rate_histogram(struct rate_hist *hist,
static int compare_img(vpx_image_t *img1, vpx_image_t *img2)
{
int match = 1;
int i, j;
int i;
match &= (img1->fmt == img2->fmt);
match &= (img1->w == img2->w);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment