/* * Copyright (c) 2010 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "vpx_config.h"#include "vp8_rtcd.h"#include "./vpx_dsp_rtcd.h"#include "bitstream.h"#include "encodemb.h"#include "encodemv.h"#if CONFIG_MULTITHREAD#include "ethreading.h"#endif#include "vp8/common/common.h"#include "onyx_int.h"#include "vp8/common/extend.h"#include "vp8/common/entropymode.h"#include "vp8/common/quant_common.h"#include "segmentation.h"#include "vp8/common/setupintrarecon.h"#include "encodeintra.h"#include "vp8/common/reconinter.h"#include "rdopt.h"#include "pickinter.h"#include "vp8/common/findnearmv.h"#include <stdio.h>#include <limits.h>#include "vp8/common/invtrans.h"#include "vpx_ports/vpx_timer.h"#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING#include "bitstream.h"#endif#include "encodeframe.h" extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t);static void adjust_act_zbin(VP8_COMP *cpi, MACROBLOCK *x); #ifdef MODE_STATSunsigned int inter_y_modes[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };unsigned int inter_uv_modes[4] = { 0, 0, 0, 0 };unsigned int inter_b_modes[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};unsigned int y_modes[5] = { 0, 0, 0, 0, 0 };unsigned int uv_modes[4] = { 0, 0, 0, 0 };unsigned int b_modes[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };#endif /* activity_avg must be positive, or flat regions could get a zero weight * (infinite lambda), which confounds analysis. * This also avoids the need for divide by zero checks in * vp8_activity_masking(). */#define VP8_ACTIVITY_AVG_MIN (64) /* This is used as a reference when computing the source variance for the * purposes of activity masking. * Eventually this should be replaced by custom no-reference routines, * which will be faster. */static const unsigned char VP8_VAR_OFFS[16] = { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }; /* Original activity measure from Tim T's code. */static unsigned int tt_activity_measure(VP8_COMP *cpi, MACROBLOCK *x) { unsigned int act; unsigned int sse; (void)cpi; /* TODO: This could also be done over smaller areas (8x8), but that would * require extensive changes elsewhere, as lambda is assumed to be fixed * over an entire MB in most of the code. * Another option is to compute four 8x8 variances, and pick a single * lambda using a non-linear combination (e.g., the smallest, or second * smallest, etc.). */ act = vpx_variance16x16(x->src.y_buffer, x->src.y_stride, VP8_VAR_OFFS, 0, &sse); act = act << 4; /* If the region is flat, lower the activity some more. */ if (act < 8 << 12) act = act < 5 << 12 ? act : 5 << 12; return act;} /* Stub for alternative experimental activity measures. */static unsigned int alt_activity_measure(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred) { return vp8_encode_intra(cpi, x, use_dc_pred);} /* Measure the activity of the current macroblock * What we measure here is TBD so abstracted to this function */#define ALT_ACT_MEASURE 1static unsigned int mb_activity_measure(VP8_COMP *cpi, MACROBLOCK *x, int mb_row, int mb_col) { unsigned int mb_activity; if (ALT_ACT_MEASURE) { int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row); /* Or use and alternative. */ mb_activity = alt_activity_measure(cpi, x, use_dc_pred); } else { /* Original activity measure from Tim T's code. */ mb_activity = tt_activity_measure(cpi, x); } if (mb_activity < VP8_ACTIVITY_AVG_MIN) mb_activity = VP8_ACTIVITY_AVG_MIN; return mb_activity;} /* Calculate an "average" mb activity value for the frame */#define ACT_MEDIAN 0static void calc_av_activity(VP8_COMP *cpi, int64_t activity_sum) {#if ACT_MEDIAN /* Find median: Simple n^2 algorithm for experimentation */ { unsigned int median; unsigned int i, j; unsigned int *sortlist; unsigned int tmp; /* Create a list to sort to */ CHECK_MEM_ERROR(sortlist, vpx_calloc(sizeof(unsigned int), cpi->common.MBs)); /* Copy map to sort list */ memcpy(sortlist, cpi->mb_activity_map, sizeof(unsigned int) * cpi->common.MBs); /* Ripple each value down to its correct position */ for (i = 1; i < cpi->common.MBs; ++i) { for (j = i; j > 0; j--) { if (sortlist[j] < sortlist[j - 1]) { /* Swap values */ tmp = sortlist[j - 1]; sortlist[j - 1] = sortlist[j]; sortlist[j] = tmp; } else break; } } /* Even number MBs so estimate median as mean of two either side. */ median = (1 + sortlist[cpi->common.MBs >> 1] + sortlist[(cpi->common.MBs >> 1) + 1]) >> 1; cpi->activity_avg = median; vpx_free(sortlist); }#else /* Simple mean for now */ cpi->activity_avg = (unsigned int)(activity_sum / cpi->common.MBs);#endif if (cpi->activity_avg < VP8_ACTIVITY_AVG_MIN) { cpi->activity_avg = VP8_ACTIVITY_AVG_MIN; } /* Experimental code: return fixed value normalized for several clips */ if (ALT_ACT_MEASURE) cpi->activity_avg = 100000;} #define USE_ACT_INDEX 0#define OUTPUT_NORM_ACT_STATS 0 #if USE_ACT_INDEX/* Calculate and activity index for each mb */static void calc_activity_index(VP8_COMP *cpi, MACROBLOCK *x) { VP8_COMMON *const cm = &cpi->common; int mb_row, mb_col; int64_t act; int64_t a; int64_t b; #if OUTPUT_NORM_ACT_STATS FILE *f = fopen("norm_act.stt", "a"); fprintf(f, "\n%12d\n", cpi->activity_avg);#endif /* Reset pointers to start of activity map */ x->mb_activity_ptr = cpi->mb_activity_map; /* Calculate normalized mb activity number. */ for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) { /* for each macroblock col in image */ for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { /* Read activity from the map */ act = *(x->mb_activity_ptr); /* Calculate a normalized activity number */ a = act + 4 * cpi->activity_avg; b = 4 * act + cpi->activity_avg; if (b >= a) *(x->activity_ptr) = (int)((b + (a >> 1)) / a) - 1; else *(x->activity_ptr) = 1 - (int)((a + (b >> 1)) / b); #if OUTPUT_NORM_ACT_STATS fprintf(f, " %6d", *(x->mb_activity_ptr));#endif /* Increment activity map pointers */ x->mb_activity_ptr++; } #if OUTPUT_NORM_ACT_STATS fprintf(f, "\n");#endif } #if OUTPUT_NORM_ACT_STATS fclose(f);#endif}#endif /* Loop through all MBs. Note activity of each, average activity and * calculate a normalized activity for each */static void build_activity_map(VP8_COMP *cpi) { MACROBLOCK *const x = &cpi->mb; MACROBLOCKD *xd = &x->e_mbd; VP8_COMMON *const cm = &cpi->common; #if ALT_ACT_MEASURE YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx]; int recon_yoffset; int recon_y_stride = new_yv12->y_stride;#endif int mb_row, mb_col; unsigned int mb_activity; int64_t activity_sum = 0; /* for each macroblock row in image */ for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {#if ALT_ACT_MEASURE /* reset above block coeffs */ xd->up_available = (mb_row != 0); recon_yoffset = (mb_row * recon_y_stride * 16);#endif /* for each macroblock col in image */ for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {#if ALT_ACT_MEASURE xd->dst.y_buffer = new_yv12->y_buffer + recon_yoffset; xd->left_available = (mb_col != 0); recon_yoffset += 16;#endif /* Copy current mb to a buffer */ vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); /* measure activity */ mb_activity = mb_activity_measure(cpi, x, mb_row, mb_col); /* Keep frame sum */ activity_sum += mb_activity; /* Store MB level activity details. */ *x->mb_activity_ptr = mb_activity; /* Increment activity map pointer */ x->mb_activity_ptr++; /* adjust to the next column of source macroblocks */ x->src.y_buffer += 16; } /* adjust to the next row of mbs */ x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols; #if ALT_ACT_MEASURE /* extend the recon for intra prediction */ vp8_extend_mb_row(new_yv12, xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);#endif } /* Calculate an "average" MB activity */ calc_av_activity(cpi, activity_sum); #if USE_ACT_INDEX /* Calculate an activity index number of each mb */ calc_activity_index(cpi, x);#endif} /* Macroblock activity masking */void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x) {#if USE_ACT_INDEX x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2); x->errorperbit = x->rdmult * 100 / (110 * x->rddiv); x->errorperbit += (x->errorperbit == 0);#else int64_t a; int64_t b; int64_t act = *(x->mb_activity_ptr); /* Apply the masking to the RD multiplier. */ a = act + (2 * cpi->activity_avg); b = (2 * act) + cpi->activity_avg; x->rdmult = (unsigned int)(((int64_t)x->rdmult * b + (a >> 1)) / a); x->errorperbit = x->rdmult * 100 / (110 * x->rddiv); x->errorperbit += (x->errorperbit == 0);#endif /* Activity based Zbin adjustment */ adjust_act_zbin(cpi, x);} static void encode_mb_row(VP8_COMP *cpi, VP8_COMMON *cm, int mb_row, MACROBLOCK *x, MACROBLOCKD *xd, TOKENEXTRA **tp, int *segment_counts, int *totalrate) { int recon_yoffset, recon_uvoffset; int mb_col; int ref_fb_idx = cm->lst_fb_idx; int dst_fb_idx = cm->new_fb_idx; int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride; int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride; int map_index = (mb_row * cpi->common.mb_cols); #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) const int num_part = (1 << cm->multi_token_partition); TOKENEXTRA *tp_start = cpi->tok; vp8_writer *w;#endif #if CONFIG_MULTITHREAD const int nsync = cpi->mt_sync_range; vpx_atomic_int rightmost_col = VPX_ATOMIC_INIT(cm->mb_cols + nsync); const vpx_atomic_int *last_row_current_mb_col; vpx_atomic_int *current_mb_col = NULL; if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) { current_mb_col = &cpi->mt_current_mb_col[mb_row]; } if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0 && mb_row != 0) { last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1]; } else { last_row_current_mb_col = &rightmost_col; }#endif #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) if (num_part > 1) w = &cpi->bc[1 + (mb_row % num_part)]; else w = &cpi->bc[1];#endif /* reset above block coeffs */ xd->above_context = cm->above_context; xd->up_available = (mb_row != 0); recon_yoffset = (mb_row * recon_y_stride * 16); recon_uvoffset = (mb_row * recon_uv_stride * 8); cpi->tplist[mb_row].start = *tp; /* printf("Main mb_row = %d\n", mb_row); */ /* Distance of Mb to the top & bottom edges, specified in 1/8th pel * units as they are always compared to values that are in 1/8th pel */ xd->mb_to_top_edge = -((mb_row * 16) << 3); xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3; /* Set up limit values for vertical motion vector components * to prevent them extending beyond the UMV borders */ x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16)); x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16); /* Set the mb activity pointer to the start of the row. */ x->mb_activity_ptr = &cpi->mb_activity_map[map_index]; /* for each macroblock col in image */ for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) *tp = cpi->tok;#endif /* Distance of Mb to the left & right edges, specified in * 1/8th pel units as they are always compared to values * that are in 1/8th pel units */ xd->mb_to_left_edge = -((mb_col * 16) << 3); xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3; /* Set up limit values for horizontal motion vector components * to prevent them extending beyond the UMV borders */ x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16)); x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16); xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset; xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset; xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset; xd->left_available = (mb_col != 0); x->rddiv = cpi->RDDIV; x->rdmult = cpi->RDMULT; /* Copy current mb to a buffer */ vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); #if CONFIG_MULTITHREAD if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) { if (((mb_col - 1) % nsync) == 0) { vpx_atomic_store_release(current_mb_col, mb_col - 1); } if (mb_row && !(mb_col & (nsync - 1))) { vp8_atomic_spin_wait(mb_col, last_row_current_mb_col, nsync); } }#endif if (cpi->oxcf.tuning == VP8_TUNE_SSIM) vp8_activity_masking(cpi, x); /* Is segmentation enabled */ /* MB level adjustment to quantizer */ if (xd->segmentation_enabled) { /* Code to set segment id in xd->mbmi.segment_id for current MB * (with range checking) */ if (cpi->segmentation_map[map_index + mb_col] <= 3) { xd->mode_info_context->mbmi.segment_id = cpi->segmentation_map[map_index + mb_col]; } else { xd->mode_info_context->mbmi.segment_id = 0; } vp8cx_mb_init_quantizer(cpi, x, 1); } else { /* Set to Segment 0 by default */ xd->mode_info_context->mbmi.segment_id = 0; } x->active_ptr = cpi->active_map + map_index + mb_col; if (cm->frame_type == KEY_FRAME) { *totalrate += vp8cx_encode_intra_macroblock(cpi, x, tp);#ifdef MODE_STATS y_modes[xd->mbmi.mode]++;#endif } else { *totalrate += vp8cx_encode_inter_macroblock( cpi, x, tp, recon_yoffset, recon_uvoffset, mb_row, mb_col); #ifdef MODE_STATS inter_y_modes[xd->mbmi.mode]++; if (xd->mbmi.mode == SPLITMV) { int b; for (b = 0; b < xd->mbmi.partition_count; ++b) { inter_b_modes[x->partition->bmi[b].mode]++; } } #endif // Keep track of how many (consecutive) times a block is coded // as ZEROMV_LASTREF, for base layer frames. // Reset to 0 if its coded as anything else. if (cpi->current_layer == 0) { if (xd->mode_info_context->mbmi.mode == ZEROMV && xd->mode_info_context->mbmi.ref_frame == LAST_FRAME) { // Increment, check for wrap-around. if (cpi->consec_zero_last[map_index + mb_col] < 255) { cpi->consec_zero_last[map_index + mb_col] += 1; } if (cpi->consec_zero_last_mvbias[map_index + mb_col] < 255) { cpi->consec_zero_last_mvbias[map_index + mb_col] += 1; } } else { cpi->consec_zero_last[map_index + mb_col] = 0; cpi->consec_zero_last_mvbias[map_index + mb_col] = 0; } if (x->zero_last_dot_suppress) { cpi->consec_zero_last_mvbias[map_index + mb_col] = 0; } } /* Special case code for cyclic refresh * If cyclic update enabled then copy xd->mbmi.segment_id; (whichLines 1–500 of 1294. Load more
/* * Copyright (c) 2010 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "vpx_config.h" #include "vp8_rtcd.h" #include "./vpx_dsp_rtcd.h" #include "bitstream.h" #include "encodemb.h" #include "encodemv.h" #if CONFIG_MULTITHREAD #include "ethreading.h" #endif #include "vp8/common/common.h" #include "onyx_int.h" #include "vp8/common/extend.h" #include "vp8/common/entropymode.h" #include "vp8/common/quant_common.h" #include "segmentation.h" #include "vp8/common/setupintrarecon.h" #include "encodeintra.h" #include "vp8/common/reconinter.h" #include "rdopt.h" #include "pickinter.h" #include "vp8/common/findnearmv.h" #include <stdio.h> #include <limits.h> #include "vp8/common/invtrans.h" #include "vpx_ports/vpx_timer.h" #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING #include "bitstream.h" #endif #include "encodeframe.h" extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t); static void adjust_act_zbin(VP8_COMP *cpi, MACROBLOCK *x); #ifdef MODE_STATS unsigned int inter_y_modes[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned int inter_uv_modes[4] = { 0, 0, 0, 0 }; unsigned int inter_b_modes[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned int y_modes[5] = { 0, 0, 0, 0, 0 }; unsigned int uv_modes[4] = { 0, 0, 0, 0 }; unsigned int b_modes[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #endif /* activity_avg must be positive, or flat regions could get a zero weight * (infinite lambda), which confounds analysis. * This also avoids the need for divide by zero checks in * vp8_activity_masking(). */ #define VP8_ACTIVITY_AVG_MIN (64) /* This is used as a reference when computing the source variance for the * purposes of activity masking. * Eventually this should be replaced by custom no-reference routines, * which will be faster. */ static const unsigned char VP8_VAR_OFFS[16] = { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }; /* Original activity measure from Tim T's code. */ static unsigned int tt_activity_measure(VP8_COMP *cpi, MACROBLOCK *x) { unsigned int act; unsigned int sse; (void)cpi; /* TODO: This could also be done over smaller areas (8x8), but that would * require extensive changes elsewhere, as lambda is assumed to be fixed * over an entire MB in most of the code. * Another option is to compute four 8x8 variances, and pick a single * lambda using a non-linear combination (e.g., the smallest, or second * smallest, etc.). */ act = vpx_variance16x16(x->src.y_buffer, x->src.y_stride, VP8_VAR_OFFS, 0, &sse); act = act << 4; /* If the region is flat, lower the activity some more. */ if (act < 8 << 12) act = act < 5 << 12 ? act : 5 << 12; return act; } /* Stub for alternative experimental activity measures. */ static unsigned int alt_activity_measure(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred) { return vp8_encode_intra(cpi, x, use_dc_pred); } /* Measure the activity of the current macroblock * What we measure here is TBD so abstracted to this function */ #define ALT_ACT_MEASURE 1 static unsigned int mb_activity_measure(VP8_COMP *cpi, MACROBLOCK *x, int mb_row, int mb_col) { unsigned int mb_activity; if (ALT_ACT_MEASURE) { int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row); /* Or use and alternative. */ mb_activity = alt_activity_measure(cpi, x, use_dc_pred); } else { /* Original activity measure from Tim T's code. */ mb_activity = tt_activity_measure(cpi, x); } if (mb_activity < VP8_ACTIVITY_AVG_MIN) mb_activity = VP8_ACTIVITY_AVG_MIN; return mb_activity; } /* Calculate an "average" mb activity value for the frame */ #define ACT_MEDIAN 0 static void calc_av_activity(VP8_COMP *cpi, int64_t activity_sum) { #if ACT_MEDIAN /* Find median: Simple n^2 algorithm for experimentation */ { unsigned int median; unsigned int i, j; unsigned int *sortlist; unsigned int tmp; /* Create a list to sort to */ CHECK_MEM_ERROR(sortlist, vpx_calloc(sizeof(unsigned int), cpi->common.MBs)); /* Copy map to sort list */ memcpy(sortlist, cpi->mb_activity_map, sizeof(unsigned int) * cpi->common.MBs); /* Ripple each value down to its correct position */ for (i = 1; i < cpi->common.MBs; ++i) { for (j = i; j > 0; j--) { if (sortlist[j] < sortlist[j - 1]) { /* Swap values */ tmp = sortlist[j - 1]; sortlist[j - 1] = sortlist[j]; sortlist[j] = tmp; } else break; } } /* Even number MBs so estimate median as mean of two either side. */ median = (1 + sortlist[cpi->common.MBs >> 1] + sortlist[(cpi->common.MBs >> 1) + 1]) >> 1; cpi->activity_avg = median; vpx_free(sortlist); } #else /* Simple mean for now */ cpi->activity_avg = (unsigned int)(activity_sum / cpi->common.MBs); #endif if (cpi->activity_avg < VP8_ACTIVITY_AVG_MIN) { cpi->activity_avg = VP8_ACTIVITY_AVG_MIN; } /* Experimental code: return fixed value normalized for several clips */ if (ALT_ACT_MEASURE) cpi->activity_avg = 100000; } #define USE_ACT_INDEX 0 #define OUTPUT_NORM_ACT_STATS 0 #if USE_ACT_INDEX /* Calculate and activity index for each mb */ static void calc_activity_index(VP8_COMP *cpi, MACROBLOCK *x) { VP8_COMMON *const cm = &cpi->common; int mb_row, mb_col; int64_t act; int64_t a; int64_t b; #if OUTPUT_NORM_ACT_STATS FILE *f = fopen("norm_act.stt", "a"); fprintf(f, "\n%12d\n", cpi->activity_avg); #endif /* Reset pointers to start of activity map */ x->mb_activity_ptr = cpi->mb_activity_map; /* Calculate normalized mb activity number. */ for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) { /* for each macroblock col in image */ for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { /* Read activity from the map */ act = *(x->mb_activity_ptr); /* Calculate a normalized activity number */ a = act + 4 * cpi->activity_avg; b = 4 * act + cpi->activity_avg; if (b >= a) *(x->activity_ptr) = (int)((b + (a >> 1)) / a) - 1; else *(x->activity_ptr) = 1 - (int)((a + (b >> 1)) / b); #if OUTPUT_NORM_ACT_STATS fprintf(f, " %6d", *(x->mb_activity_ptr)); #endif /* Increment activity map pointers */ x->mb_activity_ptr++; } #if OUTPUT_NORM_ACT_STATS fprintf(f, "\n"); #endif } #if OUTPUT_NORM_ACT_STATS fclose(f); #endif } #endif /* Loop through all MBs. Note activity of each, average activity and * calculate a normalized activity for each */ static void build_activity_map(VP8_COMP *cpi) { MACROBLOCK *const x = &cpi->mb; MACROBLOCKD *xd = &x->e_mbd; VP8_COMMON *const cm = &cpi->common; #if ALT_ACT_MEASURE YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx]; int recon_yoffset; int recon_y_stride = new_yv12->y_stride; #endif int mb_row, mb_col; unsigned int mb_activity; int64_t activity_sum = 0; /* for each macroblock row in image */ for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) { #if ALT_ACT_MEASURE /* reset above block coeffs */ xd->up_available = (mb_row != 0); recon_yoffset = (mb_row * recon_y_stride * 16); #endif /* for each macroblock col in image */ for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { #if ALT_ACT_MEASURE xd->dst.y_buffer = new_yv12->y_buffer + recon_yoffset; xd->left_available = (mb_col != 0); recon_yoffset += 16; #endif /* Copy current mb to a buffer */ vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); /* measure activity */ mb_activity = mb_activity_measure(cpi, x, mb_row, mb_col); /* Keep frame sum */ activity_sum += mb_activity; /* Store MB level activity details. */ *x->mb_activity_ptr = mb_activity; /* Increment activity map pointer */ x->mb_activity_ptr++; /* adjust to the next column of source macroblocks */ x->src.y_buffer += 16; } /* adjust to the next row of mbs */ x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols; #if ALT_ACT_MEASURE /* extend the recon for intra prediction */ vp8_extend_mb_row(new_yv12, xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8); #endif } /* Calculate an "average" MB activity */ calc_av_activity(cpi, activity_sum); #if USE_ACT_INDEX /* Calculate an activity index number of each mb */ calc_activity_index(cpi, x); #endif } /* Macroblock activity masking */ void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x) { #if USE_ACT_INDEX x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2); x->errorperbit = x->rdmult * 100 / (110 * x->rddiv); x->errorperbit += (x->errorperbit == 0); #else int64_t a; int64_t b; int64_t act = *(x->mb_activity_ptr); /* Apply the masking to the RD multiplier. */ a = act + (2 * cpi->activity_avg); b = (2 * act) + cpi->activity_avg; x->rdmult = (unsigned int)(((int64_t)x->rdmult * b + (a >> 1)) / a); x->errorperbit = x->rdmult * 100 / (110 * x->rddiv); x->errorperbit += (x->errorperbit == 0); #endif /* Activity based Zbin adjustment */ adjust_act_zbin(cpi, x); } static void encode_mb_row(VP8_COMP *cpi, VP8_COMMON *cm, int mb_row, MACROBLOCK *x, MACROBLOCKD *xd, TOKENEXTRA **tp, int *segment_counts, int *totalrate) { int recon_yoffset, recon_uvoffset; int mb_col; int ref_fb_idx = cm->lst_fb_idx; int dst_fb_idx = cm->new_fb_idx; int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride; int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride; int map_index = (mb_row * cpi->common.mb_cols); #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) const int num_part = (1 << cm->multi_token_partition); TOKENEXTRA *tp_start = cpi->tok; vp8_writer *w; #endif #if CONFIG_MULTITHREAD const int nsync = cpi->mt_sync_range; vpx_atomic_int rightmost_col = VPX_ATOMIC_INIT(cm->mb_cols + nsync); const vpx_atomic_int *last_row_current_mb_col; vpx_atomic_int *current_mb_col = NULL; if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) { current_mb_col = &cpi->mt_current_mb_col[mb_row]; } if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0 && mb_row != 0) { last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1]; } else { last_row_current_mb_col = &rightmost_col; } #endif #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) if (num_part > 1) w = &cpi->bc[1 + (mb_row % num_part)]; else w = &cpi->bc[1]; #endif /* reset above block coeffs */ xd->above_context = cm->above_context; xd->up_available = (mb_row != 0); recon_yoffset = (mb_row * recon_y_stride * 16); recon_uvoffset = (mb_row * recon_uv_stride * 8); cpi->tplist[mb_row].start = *tp; /* printf("Main mb_row = %d\n", mb_row); */ /* Distance of Mb to the top & bottom edges, specified in 1/8th pel * units as they are always compared to values that are in 1/8th pel */ xd->mb_to_top_edge = -((mb_row * 16) << 3); xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3; /* Set up limit values for vertical motion vector components * to prevent them extending beyond the UMV borders */ x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16)); x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16); /* Set the mb activity pointer to the start of the row. */ x->mb_activity_ptr = &cpi->mb_activity_map[map_index]; /* for each macroblock col in image */ for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) *tp = cpi->tok; #endif /* Distance of Mb to the left & right edges, specified in * 1/8th pel units as they are always compared to values * that are in 1/8th pel units */ xd->mb_to_left_edge = -((mb_col * 16) << 3); xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3; /* Set up limit values for horizontal motion vector components * to prevent them extending beyond the UMV borders */ x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16)); x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16); xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset; xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset; xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset; xd->left_available = (mb_col != 0); x->rddiv = cpi->RDDIV; x->rdmult = cpi->RDMULT; /* Copy current mb to a buffer */ vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); #if CONFIG_MULTITHREAD if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) { if (((mb_col - 1) % nsync) == 0) { vpx_atomic_store_release(current_mb_col, mb_col - 1); } if (mb_row && !(mb_col & (nsync - 1))) { vp8_atomic_spin_wait(mb_col, last_row_current_mb_col, nsync); } } #endif if (cpi->oxcf.tuning == VP8_TUNE_SSIM) vp8_activity_masking(cpi, x); /* Is segmentation enabled */ /* MB level adjustment to quantizer */ if (xd->segmentation_enabled) { /* Code to set segment id in xd->mbmi.segment_id for current MB * (with range checking) */ if (cpi->segmentation_map[map_index + mb_col] <= 3) { xd->mode_info_context->mbmi.segment_id = cpi->segmentation_map[map_index + mb_col]; } else { xd->mode_info_context->mbmi.segment_id = 0; } vp8cx_mb_init_quantizer(cpi, x, 1); } else { /* Set to Segment 0 by default */ xd->mode_info_context->mbmi.segment_id = 0; } x->active_ptr = cpi->active_map + map_index + mb_col; if (cm->frame_type == KEY_FRAME) { *totalrate += vp8cx_encode_intra_macroblock(cpi, x, tp); #ifdef MODE_STATS y_modes[xd->mbmi.mode]++; #endif } else { *totalrate += vp8cx_encode_inter_macroblock( cpi, x, tp, recon_yoffset, recon_uvoffset, mb_row, mb_col); #ifdef MODE_STATS inter_y_modes[xd->mbmi.mode]++; if (xd->mbmi.mode == SPLITMV) { int b; for (b = 0; b < xd->mbmi.partition_count; ++b) { inter_b_modes[x->partition->bmi[b].mode]++; } } #endif // Keep track of how many (consecutive) times a block is coded // as ZEROMV_LASTREF, for base layer frames. // Reset to 0 if its coded as anything else. if (cpi->current_layer == 0) { if (xd->mode_info_context->mbmi.mode == ZEROMV && xd->mode_info_context->mbmi.ref_frame == LAST_FRAME) { // Increment, check for wrap-around. if (cpi->consec_zero_last[map_index + mb_col] < 255) { cpi->consec_zero_last[map_index + mb_col] += 1; } if (cpi->consec_zero_last_mvbias[map_index + mb_col] < 255) { cpi->consec_zero_last_mvbias[map_index + mb_col] += 1; } } else { cpi->consec_zero_last[map_index + mb_col] = 0; cpi->consec_zero_last_mvbias[map_index + mb_col] = 0; } if (x->zero_last_dot_suppress) { cpi->consec_zero_last_mvbias[map_index + mb_col] = 0; } } /* Special case code for cyclic refresh * If cyclic update enabled then copy xd->mbmi.segment_id; (which