2010-05-18 17:58:33 +02:00
|
|
|
/*
|
2010-09-09 14:16:39 +02:00
|
|
|
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
2010-05-18 17:58:33 +02:00
|
|
|
*
|
2010-06-18 18:39:21 +02:00
|
|
|
* Use of this source code is governed by a BSD-style license
|
2010-06-04 22:19:40 +02:00
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
2010-06-18 18:39:21 +02:00
|
|
|
* in the file PATENTS. All contributing project authors may
|
2010-06-04 22:19:40 +02:00
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
2010-05-18 17:58:33 +02:00
|
|
|
*/
|
|
|
|
|
2013-08-23 00:50:51 +02:00
|
|
|
#include <limits.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2013-05-31 00:13:08 +02:00
|
|
|
#include "./vp9_rtcd.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "./vpx_config.h"
|
|
|
|
|
|
|
|
#include "vpx_ports/vpx_timer.h"
|
|
|
|
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_common.h"
|
2012-11-29 00:15:51 +01:00
|
|
|
#include "vp9/common/vp9_entropy.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_entropymode.h"
|
2013-10-08 20:27:56 +02:00
|
|
|
#include "vp9/common/vp9_idct.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/common/vp9_mvref_common.h"
|
|
|
|
#include "vp9/common/vp9_pred_common.h"
|
|
|
|
#include "vp9/common/vp9_quant_common.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_reconintra.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/common/vp9_reconinter.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_seg_common.h"
|
2014-01-10 22:48:44 +01:00
|
|
|
#include "vp9/common/vp9_systemdependent.h"
|
2013-02-07 00:30:21 +01:00
|
|
|
#include "vp9/common/vp9_tile_common.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/encoder/vp9_encodeframe.h"
|
|
|
|
#include "vp9/encoder/vp9_encodemb.h"
|
|
|
|
#include "vp9/encoder/vp9_encodemv.h"
|
2013-11-18 21:36:55 +01:00
|
|
|
#include "vp9/encoder/vp9_extend.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/encoder/vp9_onyx_int.h"
|
2014-01-10 20:51:20 +01:00
|
|
|
#include "vp9/encoder/vp9_pickmode.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/encoder/vp9_rdopt.h"
|
|
|
|
#include "vp9/encoder/vp9_segmentation.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/encoder/vp9_tokenize.h"
|
2013-10-07 20:20:10 +02:00
|
|
|
#include "vp9/encoder/vp9_vaq.h"
|
|
|
|
|
2012-11-07 19:41:04 +01:00
|
|
|
#define DBG_PRNT_SEGMAP 0
|
2010-09-24 00:25:33 +02:00
|
|
|
|
2013-09-08 15:55:17 +02:00
|
|
|
|
2012-11-16 00:14:38 +01:00
|
|
|
// #define ENC_DEBUG
|
2011-02-14 23:18:18 +01:00
|
|
|
#ifdef ENC_DEBUG
|
2012-07-14 00:21:29 +02:00
|
|
|
int enc_debug = 0;
|
2011-02-14 23:18:18 +01:00
|
|
|
#endif
|
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
static INLINE uint8_t *get_sb_index(MACROBLOCK *x, BLOCK_SIZE subsize) {
|
2013-10-16 21:35:07 +02:00
|
|
|
switch (subsize) {
|
|
|
|
case BLOCK_64X64:
|
|
|
|
case BLOCK_64X32:
|
|
|
|
case BLOCK_32X64:
|
|
|
|
case BLOCK_32X32:
|
2013-11-12 00:58:57 +01:00
|
|
|
return &x->sb_index;
|
2013-10-16 21:35:07 +02:00
|
|
|
case BLOCK_32X16:
|
|
|
|
case BLOCK_16X32:
|
|
|
|
case BLOCK_16X16:
|
2013-11-12 00:58:57 +01:00
|
|
|
return &x->mb_index;
|
2013-10-16 21:35:07 +02:00
|
|
|
case BLOCK_16X8:
|
|
|
|
case BLOCK_8X16:
|
|
|
|
case BLOCK_8X8:
|
2013-11-12 00:58:57 +01:00
|
|
|
return &x->b_index;
|
2013-10-16 21:35:07 +02:00
|
|
|
case BLOCK_8X4:
|
|
|
|
case BLOCK_4X8:
|
|
|
|
case BLOCK_4X4:
|
2013-11-12 00:58:57 +01:00
|
|
|
return &x->ab_index;
|
2013-10-16 21:35:07 +02:00
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled,
|
2013-08-27 20:05:08 +02:00
|
|
|
int mi_row, int mi_col, BLOCK_SIZE bsize);
|
2012-10-30 22:25:33 +01:00
|
|
|
|
2012-10-31 01:53:32 +01:00
|
|
|
static void adjust_act_zbin(VP9_COMP *cpi, MACROBLOCK *x);
|
2011-02-14 23:18:18 +01:00
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
// 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
|
|
|
|
// vp9_activity_masking().
|
2013-08-23 03:40:34 +02:00
|
|
|
#define ACTIVITY_AVG_MIN (64)
|
2010-10-11 23:37:27 +02:00
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
// Motion vector component magnitude threshold for defining fast motion.
|
2013-08-03 02:19:29 +02:00
|
|
|
#define FAST_MOTION_MV_THRESH (24)
|
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
// 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.
|
2013-08-01 21:56:12 +02:00
|
|
|
static const uint8_t VP9_VAR_OFFS[64] = {
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128
|
|
|
|
};
|
|
|
|
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
static unsigned int get_sby_perpixel_variance(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bs) {
|
2013-08-01 21:56:12 +02:00
|
|
|
unsigned int var, sse;
|
2014-01-07 02:38:57 +01:00
|
|
|
var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
|
2013-08-01 21:56:12 +02:00
|
|
|
VP9_VAR_OFFS, 0, &sse);
|
2014-01-07 02:38:57 +01:00
|
|
|
return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
}
|
|
|
|
|
2011-05-12 18:01:55 +02:00
|
|
|
// Original activity measure from Tim T's code.
|
2013-08-01 01:59:15 +02:00
|
|
|
static unsigned int tt_activity_measure(MACROBLOCK *x) {
|
2012-07-14 00:21:29 +02:00
|
|
|
unsigned int sse;
|
|
|
|
/* 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.).
|
|
|
|
*/
|
2014-01-10 22:48:44 +01:00
|
|
|
unsigned int act = vp9_variance16x16(x->plane[0].src.buf,
|
|
|
|
x->plane[0].src.stride,
|
|
|
|
VP9_VAR_OFFS, 0, &sse) << 4;
|
|
|
|
// If the region is flat, lower the activity some more.
|
|
|
|
if (act < (8 << 12))
|
|
|
|
act = MIN(act, 5 << 12);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
|
|
|
return act;
|
2010-10-11 23:37:27 +02:00
|
|
|
}
|
|
|
|
|
2011-05-12 18:01:55 +02:00
|
|
|
// Stub for alternative experimental activity measures.
|
2013-08-16 21:51:20 +02:00
|
|
|
static unsigned int alt_activity_measure(MACROBLOCK *x, int use_dc_pred) {
|
|
|
|
return vp9_encode_intra(x, use_dc_pred);
|
2011-05-12 18:01:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Measure the activity of the current macroblock
|
|
|
|
// What we measure here is TBD so abstracted to this function
|
2011-06-08 17:00:59 +02:00
|
|
|
#define ALT_ACT_MEASURE 1
|
2013-08-16 21:51:20 +02:00
|
|
|
static unsigned int mb_activity_measure(MACROBLOCK *x, int mb_row, int mb_col) {
|
2012-07-14 00:21:29 +02:00
|
|
|
unsigned int mb_activity;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
if (ALT_ACT_MEASURE) {
|
2014-01-10 22:48:44 +01:00
|
|
|
const int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Or use and alternative.
|
2013-08-16 21:51:20 +02:00
|
|
|
mb_activity = alt_activity_measure(x, use_dc_pred);
|
2012-07-14 00:21:29 +02:00
|
|
|
} else {
|
|
|
|
// Original activity measure from Tim T's code.
|
2013-08-01 01:59:15 +02:00
|
|
|
mb_activity = tt_activity_measure(x);
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
return MAX(mb_activity, ACTIVITY_AVG_MIN);
|
2011-05-12 18:01:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate an "average" mb activity value for the frame
|
2011-06-08 17:00:59 +02:00
|
|
|
#define ACT_MEDIAN 0
|
2012-10-31 01:53:32 +01:00
|
|
|
static void calc_av_activity(VP9_COMP *cpi, int64_t activity_sum) {
|
2011-06-08 17:00:59 +02:00
|
|
|
#if ACT_MEDIAN
|
2012-07-14 00:21:29 +02:00
|
|
|
// 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
|
2013-06-28 19:36:20 +02:00
|
|
|
CHECK_MEM_ERROR(&cpi->common, sortlist, vpx_calloc(sizeof(unsigned int),
|
|
|
|
cpi->common.MBs));
|
2012-07-14 00:21:29 +02:00
|
|
|
|
|
|
|
// Copy map to sort list
|
|
|
|
vpx_memcpy(sortlist, cpi->mb_activity_map,
|
2013-06-19 23:26:49 +02:00
|
|
|
sizeof(unsigned int) * cpi->common.MBs);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
|
|
|
// 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;
|
2013-10-04 23:37:31 +02:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
|
|
|
}
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Even number MBs so estimate median as mean of two either side.
|
|
|
|
median = (1 + sortlist[cpi->common.MBs >> 1] +
|
2013-06-19 23:26:49 +02:00
|
|
|
sortlist[(cpi->common.MBs >> 1) + 1]) >> 1;
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
cpi->activity_avg = median;
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
vpx_free(sortlist);
|
|
|
|
}
|
2011-06-08 17:00:59 +02:00
|
|
|
#else
|
2012-07-14 00:21:29 +02:00
|
|
|
// Simple mean for now
|
2013-06-19 23:26:49 +02:00
|
|
|
cpi->activity_avg = (unsigned int) (activity_sum / cpi->common.MBs);
|
2013-08-23 00:50:51 +02:00
|
|
|
#endif // ACT_MEDIAN
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2013-08-23 03:40:34 +02:00
|
|
|
if (cpi->activity_avg < ACTIVITY_AVG_MIN)
|
|
|
|
cpi->activity_avg = ACTIVITY_AVG_MIN;
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Experimental code: return fixed value normalized for several clips
|
|
|
|
if (ALT_ACT_MEASURE)
|
|
|
|
cpi->activity_avg = 100000;
|
2011-05-12 18:01:55 +02:00
|
|
|
}
|
|
|
|
|
2011-06-08 17:00:59 +02:00
|
|
|
#define USE_ACT_INDEX 0
|
2011-05-12 18:01:55 +02:00
|
|
|
#define OUTPUT_NORM_ACT_STATS 0
|
2011-06-08 17:00:59 +02:00
|
|
|
|
|
|
|
#if USE_ACT_INDEX
|
2013-03-26 14:11:52 +01:00
|
|
|
// Calculate an activity index for each mb
|
2012-10-31 01:53:32 +01:00
|
|
|
static void calc_activity_index(VP9_COMP *cpi, MACROBLOCK *x) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2012-07-14 00:21:29 +02:00
|
|
|
int mb_row, mb_col;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
int64_t act;
|
|
|
|
int64_t a;
|
|
|
|
int64_t b;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
|
|
|
#if OUTPUT_NORM_ACT_STATS
|
2012-07-14 00:21:29 +02:00
|
|
|
FILE *f = fopen("norm_act.stt", "a");
|
|
|
|
fprintf(f, "\n%12d\n", cpi->activity_avg);
|
2011-05-12 18:01:55 +02:00
|
|
|
#endif
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Reset pointers to start of activity map
|
|
|
|
x->mb_activity_ptr = cpi->mb_activity_map;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// 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);
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Calculate a normalized activity number
|
|
|
|
a = act + 4 * cpi->activity_avg;
|
|
|
|
b = 4 * act + cpi->activity_avg;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
if (b >= a)
|
2013-06-19 23:26:49 +02:00
|
|
|
*(x->activity_ptr) = (int)((b + (a >> 1)) / a) - 1;
|
2012-07-14 00:21:29 +02:00
|
|
|
else
|
2013-06-19 23:26:49 +02:00
|
|
|
*(x->activity_ptr) = 1 - (int)((a + (b >> 1)) / b);
|
2011-05-12 18:01:55 +02:00
|
|
|
|
|
|
|
#if OUTPUT_NORM_ACT_STATS
|
2012-07-14 00:21:29 +02:00
|
|
|
fprintf(f, " %6d", *(x->mb_activity_ptr));
|
2011-05-12 18:01:55 +02:00
|
|
|
#endif
|
2012-07-14 00:21:29 +02:00
|
|
|
// Increment activity map pointers
|
|
|
|
x->mb_activity_ptr++;
|
|
|
|
}
|
2011-05-12 18:01:55 +02:00
|
|
|
|
|
|
|
#if OUTPUT_NORM_ACT_STATS
|
2012-07-14 00:21:29 +02:00
|
|
|
fprintf(f, "\n");
|
2011-05-12 18:01:55 +02:00
|
|
|
#endif
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2011-05-12 18:01:55 +02:00
|
|
|
|
|
|
|
#if OUTPUT_NORM_ACT_STATS
|
2012-07-14 00:21:29 +02:00
|
|
|
fclose(f);
|
2011-05-12 18:01:55 +02:00
|
|
|
#endif
|
|
|
|
}
|
2013-08-23 00:50:51 +02:00
|
|
|
#endif // USE_ACT_INDEX
|
2011-05-12 18:01:55 +02:00
|
|
|
|
|
|
|
// Loop through all MBs. Note activity of each, average activity and
|
|
|
|
// calculate a normalized activity for each
|
2012-10-31 01:53:32 +01:00
|
|
|
static void build_activity_map(VP9_COMP *cpi) {
|
2014-01-08 23:51:00 +01:00
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
2012-07-14 00:21:29 +02:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2014-01-08 23:51:00 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2011-06-08 17:00:59 +02:00
|
|
|
#if ALT_ACT_MEASURE
|
2013-10-24 21:20:35 +02:00
|
|
|
YV12_BUFFER_CONFIG *new_yv12 = get_frame_new_buffer(cm);
|
2012-07-14 00:21:29 +02:00
|
|
|
int recon_yoffset;
|
|
|
|
int recon_y_stride = new_yv12->y_stride;
|
2011-06-08 17:00:59 +02:00
|
|
|
#endif
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
int mb_row, mb_col;
|
|
|
|
unsigned int mb_activity;
|
|
|
|
int64_t activity_sum = 0;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2013-03-26 14:11:52 +01:00
|
|
|
x->mb_activity_ptr = cpi->mb_activity_map;
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// for each macroblock row in image
|
|
|
|
for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
|
2011-06-08 17:00:59 +02:00
|
|
|
#if ALT_ACT_MEASURE
|
2012-07-14 00:21:29 +02:00
|
|
|
// reset above block coeffs
|
|
|
|
xd->up_available = (mb_row != 0);
|
|
|
|
recon_yoffset = (mb_row * recon_y_stride * 16);
|
2011-06-08 17:00:59 +02:00
|
|
|
#endif
|
2012-07-14 00:21:29 +02:00
|
|
|
// for each macroblock col in image
|
|
|
|
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
|
2011-06-08 17:00:59 +02:00
|
|
|
#if ALT_ACT_MEASURE
|
2013-04-20 00:52:17 +02:00
|
|
|
xd->plane[0].dst.buf = new_yv12->y_buffer + recon_yoffset;
|
2012-07-14 00:21:29 +02:00
|
|
|
xd->left_available = (mb_col != 0);
|
|
|
|
recon_yoffset += 16;
|
2011-06-08 17:00:59 +02:00
|
|
|
#endif
|
2011-06-23 19:54:02 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// measure activity
|
2013-08-16 21:51:20 +02:00
|
|
|
mb_activity = mb_activity_measure(x, mb_row, mb_col);
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Keep frame sum
|
|
|
|
activity_sum += mb_activity;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Store MB level activity details.
|
|
|
|
*x->mb_activity_ptr = mb_activity;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Increment activity map pointer
|
|
|
|
x->mb_activity_ptr++;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// adjust to the next column of source macroblocks
|
2013-04-24 01:22:47 +02:00
|
|
|
x->plane[0].src.buf += 16;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// adjust to the next row of mbs
|
2013-04-24 01:22:47 +02:00
|
|
|
x->plane[0].src.buf += 16 * x->plane[0].src.stride - 16 * cm->mb_cols;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Calculate an "average" MB activity
|
|
|
|
calc_av_activity(cpi, activity_sum);
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2011-06-08 17:00:59 +02:00
|
|
|
#if USE_ACT_INDEX
|
2012-07-14 00:21:29 +02:00
|
|
|
// Calculate an activity index number of each mb
|
|
|
|
calc_activity_index(cpi, x);
|
2011-06-08 17:00:59 +02:00
|
|
|
#endif
|
2011-05-12 18:01:55 +02:00
|
|
|
}
|
|
|
|
|
2011-06-08 17:00:59 +02:00
|
|
|
// Macroblock activity masking
|
2012-10-31 01:53:32 +01:00
|
|
|
void vp9_activity_masking(VP9_COMP *cpi, MACROBLOCK *x) {
|
2011-06-08 17:00:59 +02:00
|
|
|
#if USE_ACT_INDEX
|
2012-07-14 00:21:29 +02:00
|
|
|
x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2);
|
|
|
|
x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);
|
|
|
|
x->errorperbit += (x->errorperbit == 0);
|
2011-06-08 17:00:59 +02:00
|
|
|
#else
|
2014-01-10 22:48:44 +01:00
|
|
|
const int64_t act = *(x->mb_activity_ptr);
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Apply the masking to the RD multiplier.
|
2014-01-10 22:48:44 +01:00
|
|
|
const int64_t a = act + (2 * cpi->activity_avg);
|
|
|
|
const int64_t b = (2 * act) + cpi->activity_avg;
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
x->rdmult = (unsigned int) (((int64_t) x->rdmult * b + (a >> 1)) / a);
|
2012-07-14 00:21:29 +02:00
|
|
|
x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);
|
|
|
|
x->errorperbit += (x->errorperbit == 0);
|
2011-06-08 17:00:59 +02:00
|
|
|
#endif
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Activity based Zbin adjustment
|
|
|
|
adjust_act_zbin(cpi, x);
|
2011-05-12 18:01:55 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-11-22 18:21:53 +01:00
|
|
|
// Select a segment for the current SB64
|
|
|
|
static void select_in_frame_q_segment(VP9_COMP *cpi,
|
|
|
|
int mi_row, int mi_col,
|
|
|
|
int output_enabled, int projected_rate) {
|
2014-01-08 23:51:00 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2013-11-22 18:21:53 +01:00
|
|
|
int target_rate = cpi->rc.sb64_target_rate << 8; // convert to bits << 8
|
|
|
|
|
|
|
|
const int mi_offset = mi_row * cm->mi_cols + mi_col;
|
2013-12-19 22:43:45 +01:00
|
|
|
const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
|
|
|
|
const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
|
2013-11-22 18:21:53 +01:00
|
|
|
const int xmis = MIN(cm->mi_cols - mi_col, bw);
|
|
|
|
const int ymis = MIN(cm->mi_rows - mi_row, bh);
|
|
|
|
int complexity_metric = 64;
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
unsigned char segment;
|
|
|
|
|
|
|
|
if (!output_enabled) {
|
|
|
|
segment = 0;
|
|
|
|
} else {
|
|
|
|
// Rate depends on fraction of a SB64 in frame (xmis * ymis / bw * bh).
|
|
|
|
// It is converted to bits * 256 units
|
|
|
|
target_rate = (cpi->rc.sb64_target_rate * xmis * ymis * 256) / (bw * bh);
|
|
|
|
|
|
|
|
if (projected_rate < (target_rate / 4)) {
|
|
|
|
segment = 2;
|
|
|
|
} else if (projected_rate < (target_rate / 2)) {
|
|
|
|
segment = 1;
|
|
|
|
} else {
|
|
|
|
segment = 0;
|
|
|
|
}
|
|
|
|
|
2014-01-29 15:59:04 +01:00
|
|
|
if (target_rate > 0) {
|
|
|
|
complexity_metric =
|
|
|
|
clamp((int)((projected_rate * 64) / target_rate), 16, 255);
|
|
|
|
}
|
2013-11-22 18:21:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in the entires in the segment map corresponding to this SB64
|
|
|
|
for (y = 0; y < ymis; y++) {
|
|
|
|
for (x = 0; x < xmis; x++) {
|
|
|
|
cpi->segmentation_map[mi_offset + y * cm->mi_cols + x] = segment;
|
|
|
|
cpi->complexity_map[mi_offset + y * cm->mi_cols + x] =
|
|
|
|
(unsigned char)complexity_metric;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize, int output_enabled) {
|
2013-01-06 03:20:25 +01:00
|
|
|
int i, x_idx, y;
|
2013-08-06 20:04:31 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-11-01 20:53:37 +01:00
|
|
|
struct macroblock_plane *const p = x->plane;
|
|
|
|
struct macroblockd_plane *const pd = xd->plane;
|
2012-07-14 00:21:29 +02:00
|
|
|
MODE_INFO *mi = &ctx->mic;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
|
|
|
MODE_INFO *mi_addr = xd->mi_8x8[0];
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
const int mb_mode_index = ctx->best_mode_index;
|
2013-08-06 20:04:31 +02:00
|
|
|
const int mis = cm->mode_info_stride;
|
2013-07-23 15:51:44 +02:00
|
|
|
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
2013-08-05 21:15:52 +02:00
|
|
|
const int mi_height = num_8x8_blocks_high_lookup[bsize];
|
2013-11-07 23:56:58 +01:00
|
|
|
int max_plane;
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-07-10 23:27:20 +02:00
|
|
|
assert(mi->mbmi.mode < MB_MODE_COUNT);
|
2013-06-06 22:44:34 +02:00
|
|
|
assert(mi->mbmi.ref_frame[0] < MAX_REF_FRAMES);
|
|
|
|
assert(mi->mbmi.ref_frame[1] < MAX_REF_FRAMES);
|
2013-05-11 02:06:37 +02:00
|
|
|
assert(mi->mbmi.sb_type == bsize);
|
2013-06-28 19:36:20 +02:00
|
|
|
|
2013-11-22 18:21:53 +01:00
|
|
|
// For in frame adaptive Q copy over the chosen segment id into the
|
|
|
|
// mode innfo context for the chosen mode / partition.
|
|
|
|
if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && output_enabled)
|
|
|
|
mi->mbmi.segment_id = xd->mi_8x8[0]->mbmi.segment_id;
|
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
*mi_addr = *mi;
|
|
|
|
|
2013-11-07 23:56:58 +01:00
|
|
|
max_plane = is_inter_block(mbmi) ? MAX_MB_PLANE : 1;
|
|
|
|
for (i = 0; i < max_plane; ++i) {
|
2013-11-01 20:53:37 +01:00
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][1];
|
2013-11-27 03:52:10 +01:00
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][1];
|
2013-11-01 20:53:37 +01:00
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][1];
|
2013-12-04 02:59:32 +01:00
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][1];
|
2013-11-01 20:53:37 +01:00
|
|
|
}
|
|
|
|
|
2013-11-07 23:56:58 +01:00
|
|
|
for (i = max_plane; i < MAX_MB_PLANE; ++i) {
|
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][2];
|
2013-11-27 03:52:10 +01:00
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][2];
|
2013-11-07 23:56:58 +01:00
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][2];
|
2013-12-04 02:59:32 +01:00
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][2];
|
2013-11-07 23:56:58 +01:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Restore the coding context of the MB to that that was in place
|
|
|
|
// when the mode was picked for it
|
2013-08-06 20:04:31 +02:00
|
|
|
for (y = 0; y < mi_height; y++)
|
|
|
|
for (x_idx = 0; x_idx < mi_width; x_idx++)
|
2013-08-22 23:45:24 +02:00
|
|
|
if ((xd->mb_to_right_edge >> (3 + MI_SIZE_LOG2)) + mi_width > x_idx
|
2013-11-22 18:21:53 +01:00
|
|
|
&& (xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height > y) {
|
2013-09-11 19:45:44 +02:00
|
|
|
xd->mi_8x8[x_idx + y * mis] = mi_addr;
|
2013-11-22 18:21:53 +01:00
|
|
|
}
|
2013-08-06 20:04:31 +02:00
|
|
|
|
2013-11-22 18:21:53 +01:00
|
|
|
if ((cpi->oxcf.aq_mode == VARIANCE_AQ) ||
|
|
|
|
(cpi->oxcf.aq_mode == COMPLEXITY_AQ)) {
|
2013-10-07 20:20:10 +02:00
|
|
|
vp9_mb_init_quantizer(cpi, x);
|
|
|
|
}
|
|
|
|
|
2013-07-08 23:49:33 +02:00
|
|
|
// FIXME(rbultje) I'm pretty sure this should go to the end of this block
|
|
|
|
// (i.e. after the output_enabled)
|
2013-08-02 20:45:21 +02:00
|
|
|
if (bsize < BLOCK_32X32) {
|
|
|
|
if (bsize < BLOCK_16X16)
|
2013-08-03 02:28:23 +02:00
|
|
|
ctx->tx_rd_diff[ALLOW_16X16] = ctx->tx_rd_diff[ALLOW_8X8];
|
|
|
|
ctx->tx_rd_diff[ALLOW_32X32] = ctx->tx_rd_diff[ALLOW_16X16];
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-08-02 20:45:21 +02:00
|
|
|
if (is_inter_block(mbmi) && mbmi->sb_type < BLOCK_8X8) {
|
2013-07-18 01:46:53 +02:00
|
|
|
mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
|
|
|
|
mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
|
|
|
|
2013-01-07 20:02:14 +01:00
|
|
|
x->skip = ctx->skip;
|
2013-09-21 01:29:24 +02:00
|
|
|
vpx_memcpy(x->zcoeff_blk[mbmi->tx_size], ctx->zcoeff_blk,
|
2013-10-16 21:43:03 +02:00
|
|
|
sizeof(uint8_t) * ctx->num_4x4_blk);
|
2013-09-21 01:29:24 +02:00
|
|
|
|
2013-01-06 03:20:25 +01:00
|
|
|
if (!output_enabled)
|
|
|
|
return;
|
|
|
|
|
2013-08-14 20:20:33 +02:00
|
|
|
if (!vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
|
2013-07-29 22:38:40 +02:00
|
|
|
for (i = 0; i < TX_MODES; i++)
|
2013-08-03 02:28:23 +02:00
|
|
|
cpi->rd_tx_select_diff[i] += ctx->tx_rd_diff[i];
|
2012-10-09 18:18:21 +02:00
|
|
|
}
|
|
|
|
|
2013-10-03 18:07:24 +02:00
|
|
|
if (frame_is_intra_only(cm)) {
|
2012-07-03 22:57:27 +02:00
|
|
|
#if CONFIG_INTERNAL_STATS
|
2012-07-14 00:21:29 +02:00
|
|
|
static const int kf_mode_index[] = {
|
|
|
|
THR_DC /*DC_PRED*/,
|
|
|
|
THR_V_PRED /*V_PRED*/,
|
|
|
|
THR_H_PRED /*H_PRED*/,
|
|
|
|
THR_D45_PRED /*D45_PRED*/,
|
|
|
|
THR_D135_PRED /*D135_PRED*/,
|
|
|
|
THR_D117_PRED /*D117_PRED*/,
|
|
|
|
THR_D153_PRED /*D153_PRED*/,
|
2013-08-24 02:33:48 +02:00
|
|
|
THR_D207_PRED /*D207_PRED*/,
|
2012-07-14 00:21:29 +02:00
|
|
|
THR_D63_PRED /*D63_PRED*/,
|
|
|
|
THR_TM /*TM_PRED*/,
|
|
|
|
};
|
2013-07-11 00:07:53 +02:00
|
|
|
cpi->mode_chosen_counts[kf_mode_index[mi->mbmi.mode]]++;
|
2012-07-03 22:57:27 +02:00
|
|
|
#endif
|
2012-07-14 00:21:29 +02:00
|
|
|
} else {
|
|
|
|
// Note how often each mode chosen as best
|
|
|
|
cpi->mode_chosen_counts[mb_mode_index]++;
|
2014-01-10 22:48:44 +01:00
|
|
|
if (is_inter_block(mbmi) &&
|
|
|
|
(mbmi->sb_type < BLOCK_8X8 || mbmi->mode == NEWMV)) {
|
2013-09-25 00:55:49 +02:00
|
|
|
int_mv best_mv[2];
|
2014-01-22 18:10:44 +01:00
|
|
|
for (i = 0; i < 1 + has_second_ref(mbmi); ++i)
|
2014-01-18 02:15:34 +01:00
|
|
|
best_mv[i].as_int = mbmi->ref_mvs[mbmi->ref_frame[i]][0].as_int;
|
2013-09-25 00:55:49 +02:00
|
|
|
vp9_update_mv_count(cpi, x, best_mv);
|
2013-05-02 23:38:01 +02:00
|
|
|
}
|
2013-05-05 07:09:43 +02:00
|
|
|
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cm->interp_filter == SWITCHABLE && is_inter_mode(mbmi->mode)) {
|
2013-08-06 20:04:31 +02:00
|
|
|
const int ctx = vp9_get_pred_context_switchable_interp(xd);
|
|
|
|
++cm->counts.switchable_interp[ctx][mbmi->interp_filter];
|
2012-11-30 01:39:15 +01:00
|
|
|
}
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-11-23 01:35:37 +01:00
|
|
|
cpi->rd_comp_pred_diff[SINGLE_REFERENCE] += ctx->single_pred_diff;
|
|
|
|
cpi->rd_comp_pred_diff[COMPOUND_REFERENCE] += ctx->comp_pred_diff;
|
|
|
|
cpi->rd_comp_pred_diff[REFERENCE_MODE_SELECT] += ctx->hybrid_pred_diff;
|
2013-07-08 23:49:33 +02:00
|
|
|
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
|
2013-07-08 23:49:33 +02:00
|
|
|
cpi->rd_filter_diff[i] += ctx->best_filter_diff[i];
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2012-04-07 01:38:34 +02:00
|
|
|
}
|
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
void vp9_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src,
|
2013-10-01 20:54:10 +02:00
|
|
|
int mi_row, int mi_col) {
|
|
|
|
uint8_t *const buffers[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
|
|
|
|
src->alpha_buffer};
|
|
|
|
const int strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
|
|
|
|
src->alpha_stride};
|
2013-05-16 02:55:08 +02:00
|
|
|
int i;
|
|
|
|
|
2013-12-13 05:33:06 +01:00
|
|
|
// Set current frame pointer.
|
|
|
|
x->e_mbd.cur_buf = src;
|
|
|
|
|
2013-10-01 20:54:10 +02:00
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++)
|
|
|
|
setup_pred_plane(&x->plane[i].src, buffers[i], strides[i], mi_row, mi_col,
|
2013-06-19 23:26:49 +02:00
|
|
|
NULL, x->e_mbd.plane[i].subsampling_x,
|
2013-05-16 02:55:08 +02:00
|
|
|
x->e_mbd.plane[i].subsampling_y);
|
2013-04-24 01:22:47 +02:00
|
|
|
}
|
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
static void set_offsets(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
int mi_row, int mi_col, BLOCK_SIZE bsize) {
|
2013-08-27 20:05:08 +02:00
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-01-06 03:20:25 +01:00
|
|
|
MB_MODE_INFO *mbmi;
|
2013-04-26 20:57:17 +02:00
|
|
|
const int idx_str = xd->mode_info_stride * mi_row + mi_col;
|
2013-07-23 15:51:44 +02:00
|
|
|
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
const int mi_height = num_8x8_blocks_high_lookup[bsize];
|
2013-05-05 07:09:43 +02:00
|
|
|
const int mb_row = mi_row >> 1;
|
|
|
|
const int mb_col = mi_col >> 1;
|
2013-01-06 03:20:25 +01:00
|
|
|
const int idx_map = mb_row * cm->mb_cols + mb_col;
|
2013-08-14 20:20:33 +02:00
|
|
|
const struct segmentation *const seg = &cm->seg;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-10-24 18:10:59 +02:00
|
|
|
set_skip_context(xd, cpi->above_context, cpi->left_context, mi_row, mi_col);
|
2013-04-23 19:12:18 +02:00
|
|
|
|
2013-01-06 03:20:25 +01:00
|
|
|
// Activity map pointer
|
|
|
|
x->mb_activity_ptr = &cpi->mb_activity_map[idx_map];
|
|
|
|
x->active_ptr = cpi->active_map + idx_map;
|
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
xd->mi_8x8 = cm->mi_grid_visible + idx_str;
|
|
|
|
xd->prev_mi_8x8 = cm->prev_mi_grid_visible + idx_str;
|
|
|
|
|
2013-05-29 22:42:23 +02:00
|
|
|
// Special case: if prev_mi is NULL, the previous mode info context
|
|
|
|
// cannot be used.
|
2013-09-11 19:45:44 +02:00
|
|
|
xd->last_mi = cm->prev_mi ? xd->prev_mi_8x8[0] : NULL;
|
|
|
|
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0] = cm->mi + idx_str;
|
2013-09-11 19:45:44 +02:00
|
|
|
|
2013-10-10 21:11:44 +02:00
|
|
|
mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
|
|
|
// Set up destination pointers
|
2014-01-13 23:04:56 +01:00
|
|
|
setup_dst_planes(xd, get_frame_new_buffer(cm), mi_row, mi_col);
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-08-11 00:04:02 +02:00
|
|
|
// Set up limit values for MV components
|
|
|
|
// mv beyond the range do not produce new/different prediction block
|
2013-08-23 22:29:32 +02:00
|
|
|
x->mv_row_min = -(((mi_row + mi_height) * MI_SIZE) + VP9_INTERP_EXTEND);
|
|
|
|
x->mv_col_min = -(((mi_col + mi_width) * MI_SIZE) + VP9_INTERP_EXTEND);
|
2013-08-11 00:04:02 +02:00
|
|
|
x->mv_row_max = (cm->mi_rows - mi_row) * MI_SIZE + VP9_INTERP_EXTEND;
|
|
|
|
x->mv_col_max = (cm->mi_cols - mi_col) * MI_SIZE + VP9_INTERP_EXTEND;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
|
|
|
// Set up distance of MB to edge of frame in 1/8th pel units
|
2013-07-23 15:51:44 +02:00
|
|
|
assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
|
2013-10-25 17:18:04 +02:00
|
|
|
set_mi_row_col(xd, tile, mi_row, mi_height, mi_col, mi_width,
|
|
|
|
cm->mi_rows, cm->mi_cols);
|
2013-01-06 03:20:25 +01:00
|
|
|
|
|
|
|
/* set up source buffers */
|
2013-04-26 20:57:17 +02:00
|
|
|
vp9_setup_src_planes(x, cpi->Source, mi_row, mi_col);
|
2013-01-06 03:20:25 +01:00
|
|
|
|
|
|
|
/* R/D setup */
|
|
|
|
x->rddiv = cpi->RDDIV;
|
|
|
|
x->rdmult = cpi->RDMULT;
|
|
|
|
|
|
|
|
/* segment ID */
|
2013-08-01 23:53:14 +02:00
|
|
|
if (seg->enabled) {
|
2013-11-22 18:21:53 +01:00
|
|
|
if (cpi->oxcf.aq_mode != VARIANCE_AQ) {
|
2014-01-10 22:48:44 +01:00
|
|
|
const uint8_t *const map = seg->update_map ? cpi->segmentation_map
|
|
|
|
: cm->last_frame_seg_map;
|
2013-10-07 20:20:10 +02:00
|
|
|
mbmi->segment_id = vp9_get_segment_id(cm, map, bsize, mi_row, mi_col);
|
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
vp9_mb_init_quantizer(cpi, x);
|
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
if (seg->enabled && cpi->seg0_cnt > 0 &&
|
|
|
|
!vp9_segfeature_active(seg, 0, SEG_LVL_REF_FRAME) &&
|
|
|
|
vp9_segfeature_active(seg, 1, SEG_LVL_REF_FRAME)) {
|
2013-01-06 03:20:25 +01:00
|
|
|
cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt;
|
|
|
|
} else {
|
|
|
|
const int y = mb_row & ~3;
|
|
|
|
const int x = mb_col & ~3;
|
2013-06-19 23:26:49 +02:00
|
|
|
const int p16 = ((mb_row & 1) << 1) + (mb_col & 1);
|
2013-01-06 03:20:25 +01:00
|
|
|
const int p32 = ((mb_row & 2) << 2) + ((mb_col & 2) << 1);
|
2013-10-25 17:18:04 +02:00
|
|
|
const int tile_progress = tile->mi_col_start * cm->mb_rows >> 1;
|
|
|
|
const int mb_cols = (tile->mi_col_end - tile->mi_col_start) >> 1;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
cpi->seg0_progress = ((y * mb_cols + x * 4 + p32 + p16 + tile_progress)
|
|
|
|
<< 16) / cm->MBs;
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
|
|
|
|
x->encode_breakout = cpi->segment_encode_breakout[mbmi->segment_id];
|
2013-01-06 03:20:25 +01:00
|
|
|
} else {
|
|
|
|
mbmi->segment_id = 0;
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
x->encode_breakout = cpi->oxcf.encode_breakout;
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-17 00:59:40 +01:00
|
|
|
static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
int mi_row, int mi_col,
|
|
|
|
int *totalrate, int64_t *totaldist,
|
|
|
|
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
|
|
|
|
int64_t best_rd) {
|
2013-07-11 00:57:28 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-11-01 20:53:37 +01:00
|
|
|
struct macroblock_plane *const p = x->plane;
|
|
|
|
struct macroblockd_plane *const pd = xd->plane;
|
|
|
|
int i;
|
2013-10-07 20:20:10 +02:00
|
|
|
int orig_rdmult = x->rdmult;
|
2013-10-17 20:04:57 +02:00
|
|
|
double rdmult_ratio;
|
|
|
|
|
|
|
|
vp9_clear_system_state(); // __asm emms;
|
|
|
|
rdmult_ratio = 1.0; // avoid uninitialized warnings
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-08-20 21:55:41 +02:00
|
|
|
// Use the lower precision, but faster, 32x32 fdct for mode selection.
|
2013-08-08 00:22:51 +02:00
|
|
|
x->use_lp32x32fdct = 1;
|
2013-06-14 20:28:56 +02:00
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize < BLOCK_8X8) {
|
2013-08-01 18:04:15 +02:00
|
|
|
// When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
|
|
|
|
// there is nothing to be done.
|
2013-11-12 00:58:57 +01:00
|
|
|
if (x->ab_index != 0) {
|
2013-08-01 23:57:46 +02:00
|
|
|
*totalrate = 0;
|
|
|
|
*totaldist = 0;
|
2013-05-11 02:06:37 +02:00
|
|
|
return;
|
2013-08-01 23:57:46 +02:00
|
|
|
}
|
2013-08-01 18:04:15 +02:00
|
|
|
}
|
2013-05-11 02:06:37 +02:00
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, bsize);
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->mbmi.sb_type = bsize;
|
2013-07-31 18:33:58 +02:00
|
|
|
|
2013-11-01 20:53:37 +01:00
|
|
|
for (i = 0; i < MAX_MB_PLANE; ++i) {
|
2013-11-06 06:07:08 +01:00
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][0];
|
2013-11-27 03:52:10 +01:00
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][0];
|
2013-11-06 06:07:08 +01:00
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][0];
|
2013-12-04 02:59:32 +01:00
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][0];
|
2013-11-01 20:53:37 +01:00
|
|
|
}
|
2013-11-06 06:07:08 +01:00
|
|
|
ctx->is_coded = 0;
|
2013-11-07 23:56:58 +01:00
|
|
|
x->skip_recode = 0;
|
2013-11-01 20:53:37 +01:00
|
|
|
|
2013-08-22 14:51:04 +02:00
|
|
|
// Set to zero to make sure we do not use the previous encoded frame stats
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->mbmi.skip_coeff = 0;
|
2013-08-22 14:51:04 +02:00
|
|
|
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
x->source_variance = get_sby_perpixel_variance(cpi, x, bsize);
|
2013-08-22 14:51:04 +02:00
|
|
|
|
2013-11-14 19:23:57 +01:00
|
|
|
if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
|
2014-01-10 22:48:44 +01:00
|
|
|
const int energy = bsize <= BLOCK_16X16 ? x->mb_energy
|
|
|
|
: vp9_block_energy(cpi, x, bsize);
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->mbmi.segment_id = vp9_vaq_segment_id(energy);
|
2013-10-07 20:20:10 +02:00
|
|
|
rdmult_ratio = vp9_vaq_rdmult_ratio(energy);
|
|
|
|
vp9_mb_init_quantizer(cpi, x);
|
|
|
|
}
|
|
|
|
|
2013-01-06 03:20:25 +01:00
|
|
|
if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
|
2012-10-30 20:58:42 +01:00
|
|
|
vp9_activity_masking(cpi, x);
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-11-14 19:23:57 +01:00
|
|
|
if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
|
2013-10-17 20:04:57 +02:00
|
|
|
vp9_clear_system_state(); // __asm emms;
|
|
|
|
x->rdmult = round(x->rdmult * rdmult_ratio);
|
2013-11-22 18:21:53 +01:00
|
|
|
} else if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
|
|
|
|
const int mi_offset = mi_row * cm->mi_cols + mi_col;
|
|
|
|
unsigned char complexity = cpi->complexity_map[mi_offset];
|
|
|
|
const int is_edge = (mi_row == 0) || (mi_row == (cm->mi_rows - 1)) ||
|
|
|
|
(mi_col == 0) || (mi_col == (cm->mi_cols - 1));
|
|
|
|
|
|
|
|
if (!is_edge && (complexity > 128))
|
|
|
|
x->rdmult = x->rdmult + ((x->rdmult * (complexity - 128)) / 256);
|
2013-10-17 20:04:57 +02:00
|
|
|
}
|
2013-10-07 20:20:10 +02:00
|
|
|
|
2013-07-11 00:57:28 +02:00
|
|
|
// Find best coding mode & reconstruct the MB so it is available
|
|
|
|
// as a predictor for MBs that follow in the SB
|
2013-10-03 18:07:24 +02:00
|
|
|
if (frame_is_intra_only(cm)) {
|
2013-07-17 18:56:46 +02:00
|
|
|
vp9_rd_pick_intra_mode_sb(cpi, x, totalrate, totaldist, bsize, ctx,
|
|
|
|
best_rd);
|
2013-09-28 01:02:49 +02:00
|
|
|
} else {
|
|
|
|
if (bsize >= BLOCK_8X8)
|
2013-10-25 17:18:04 +02:00
|
|
|
vp9_rd_pick_inter_mode_sb(cpi, x, tile, mi_row, mi_col,
|
|
|
|
totalrate, totaldist, bsize, ctx, best_rd);
|
2013-09-28 01:02:49 +02:00
|
|
|
else
|
2013-10-25 17:18:04 +02:00
|
|
|
vp9_rd_pick_inter_mode_sub8x8(cpi, x, tile, mi_row, mi_col, totalrate,
|
2013-09-28 01:02:49 +02:00
|
|
|
totaldist, bsize, ctx, best_rd);
|
|
|
|
}
|
2013-10-07 20:20:10 +02:00
|
|
|
|
2013-11-14 19:23:57 +01:00
|
|
|
if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
|
2013-10-17 20:04:57 +02:00
|
|
|
x->rdmult = orig_rdmult;
|
|
|
|
if (*totalrate != INT_MAX) {
|
|
|
|
vp9_clear_system_state(); // __asm emms;
|
|
|
|
*totalrate = round(*totalrate * rdmult_ratio);
|
|
|
|
}
|
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-08-01 01:59:15 +02:00
|
|
|
static void update_stats(VP9_COMP *cpi) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MODE_INFO *mi = xd->mi_8x8[0];
|
2013-08-01 01:59:15 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &mi->mbmi;
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-10-03 18:07:24 +02:00
|
|
|
if (!frame_is_intra_only(cm)) {
|
2013-08-14 20:20:33 +02:00
|
|
|
const int seg_ref_active = vp9_segfeature_active(&cm->seg, mbmi->segment_id,
|
2013-07-10 21:29:43 +02:00
|
|
|
SEG_LVL_REF_FRAME);
|
2013-06-07 20:54:20 +02:00
|
|
|
|
|
|
|
if (!seg_ref_active)
|
2013-12-19 03:52:58 +01:00
|
|
|
cm->counts.intra_inter[vp9_get_intra_inter_context(xd)]
|
2013-08-23 00:50:51 +02:00
|
|
|
[is_inter_block(mbmi)]++;
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-06-07 15:59:53 +02:00
|
|
|
// If the segment reference feature is enabled we have only a single
|
|
|
|
// reference frame allowed for the segment so exclude it from
|
|
|
|
// the reference frame counts used to work out probabilities.
|
2013-08-23 00:50:51 +02:00
|
|
|
if (is_inter_block(mbmi) && !seg_ref_active) {
|
2013-12-10 00:13:34 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT)
|
2013-12-17 05:12:47 +01:00
|
|
|
cm->counts.comp_inter[vp9_get_reference_mode_context(cm, xd)]
|
2013-08-23 00:50:51 +02:00
|
|
|
[has_second_ref(mbmi)]++;
|
2013-06-06 22:44:34 +02:00
|
|
|
|
2013-08-23 00:50:51 +02:00
|
|
|
if (has_second_ref(mbmi)) {
|
2013-12-17 05:12:47 +01:00
|
|
|
cm->counts.comp_ref[vp9_get_pred_context_comp_ref_p(cm, xd)]
|
2013-08-23 00:50:51 +02:00
|
|
|
[mbmi->ref_frame[0] == GOLDEN_FRAME]++;
|
2013-06-06 22:44:34 +02:00
|
|
|
} else {
|
2013-12-17 05:12:47 +01:00
|
|
|
cm->counts.single_ref[vp9_get_pred_context_single_ref_p1(xd)][0]
|
2013-08-23 00:50:51 +02:00
|
|
|
[mbmi->ref_frame[0] != LAST_FRAME]++;
|
2013-06-06 22:44:34 +02:00
|
|
|
if (mbmi->ref_frame[0] != LAST_FRAME)
|
2013-12-17 05:12:47 +01:00
|
|
|
cm->counts.single_ref[vp9_get_pred_context_single_ref_p2(xd)][1]
|
2013-08-23 00:50:51 +02:00
|
|
|
[mbmi->ref_frame[0] != GOLDEN_FRAME]++;
|
2013-06-06 22:44:34 +02:00
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-08-27 20:05:08 +02:00
|
|
|
static BLOCK_SIZE *get_sb_partitioning(MACROBLOCK *x, BLOCK_SIZE bsize) {
|
2013-05-08 23:24:43 +02:00
|
|
|
switch (bsize) {
|
2013-08-02 19:48:27 +02:00
|
|
|
case BLOCK_64X64:
|
2013-05-08 23:24:43 +02:00
|
|
|
return &x->sb64_partitioning;
|
2013-08-02 19:48:27 +02:00
|
|
|
case BLOCK_32X32:
|
2013-11-12 00:58:57 +01:00
|
|
|
return &x->sb_partitioning[x->sb_index];
|
2013-08-02 19:48:27 +02:00
|
|
|
case BLOCK_16X16:
|
2013-11-12 00:58:57 +01:00
|
|
|
return &x->mb_partitioning[x->sb_index][x->mb_index];
|
2013-08-02 19:48:27 +02:00
|
|
|
case BLOCK_8X8:
|
2013-11-12 00:58:57 +01:00
|
|
|
return &x->b_partitioning[x->sb_index][x->mb_index][x->b_index];
|
2013-05-08 23:24:43 +02:00
|
|
|
default:
|
|
|
|
assert(0);
|
2013-10-04 23:37:31 +02:00
|
|
|
return NULL;
|
2013-05-08 23:24:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void restore_context(VP9_COMP *cpi, int mi_row, int mi_col,
|
|
|
|
ENTROPY_CONTEXT a[16 * MAX_MB_PLANE],
|
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE],
|
2013-06-19 23:26:49 +02:00
|
|
|
PARTITION_CONTEXT sa[8], PARTITION_CONTEXT sl[8],
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize) {
|
2013-08-05 21:15:52 +02:00
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-05-08 23:24:43 +02:00
|
|
|
int p;
|
2013-08-05 21:15:52 +02:00
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
|
2013-07-23 15:51:44 +02:00
|
|
|
int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
int mi_height = num_8x8_blocks_high_lookup[bsize];
|
2013-05-08 23:24:43 +02:00
|
|
|
for (p = 0; p < MAX_MB_PLANE; p++) {
|
2013-06-19 23:26:49 +02:00
|
|
|
vpx_memcpy(
|
2013-10-24 18:10:59 +02:00
|
|
|
cpi->above_context[p] + ((mi_col * 2) >> xd->plane[p].subsampling_x),
|
2013-07-23 15:51:44 +02:00
|
|
|
a + num_4x4_blocks_wide * p,
|
|
|
|
(sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide) >>
|
|
|
|
xd->plane[p].subsampling_x);
|
2013-06-19 23:26:49 +02:00
|
|
|
vpx_memcpy(
|
2013-10-24 18:10:59 +02:00
|
|
|
cpi->left_context[p]
|
2013-07-23 15:51:44 +02:00
|
|
|
+ ((mi_row & MI_MASK) * 2 >> xd->plane[p].subsampling_y),
|
|
|
|
l + num_4x4_blocks_high * p,
|
|
|
|
(sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high) >>
|
|
|
|
xd->plane[p].subsampling_y);
|
|
|
|
}
|
2013-10-24 18:10:59 +02:00
|
|
|
vpx_memcpy(cpi->above_seg_context + mi_col, sa,
|
|
|
|
sizeof(*cpi->above_seg_context) * mi_width);
|
|
|
|
vpx_memcpy(cpi->left_seg_context + (mi_row & MI_MASK), sl,
|
|
|
|
sizeof(cpi->left_seg_context[0]) * mi_height);
|
2013-07-02 03:18:50 +02:00
|
|
|
}
|
2013-05-31 00:13:08 +02:00
|
|
|
static void save_context(VP9_COMP *cpi, int mi_row, int mi_col,
|
2013-06-19 23:26:49 +02:00
|
|
|
ENTROPY_CONTEXT a[16 * MAX_MB_PLANE],
|
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE],
|
|
|
|
PARTITION_CONTEXT sa[8], PARTITION_CONTEXT sl[8],
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize) {
|
2013-08-05 21:15:52 +02:00
|
|
|
const MACROBLOCK *const x = &cpi->mb;
|
|
|
|
const MACROBLOCKD *const xd = &x->e_mbd;
|
2013-05-31 00:13:08 +02:00
|
|
|
int p;
|
2013-08-05 21:15:52 +02:00
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
|
2013-07-23 15:51:44 +02:00
|
|
|
int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
int mi_height = num_8x8_blocks_high_lookup[bsize];
|
2013-05-31 00:13:08 +02:00
|
|
|
|
|
|
|
// buffer the above/left context information of the block in search.
|
|
|
|
for (p = 0; p < MAX_MB_PLANE; ++p) {
|
2013-06-19 23:26:49 +02:00
|
|
|
vpx_memcpy(
|
2013-07-23 15:51:44 +02:00
|
|
|
a + num_4x4_blocks_wide * p,
|
2013-10-24 18:10:59 +02:00
|
|
|
cpi->above_context[p] + (mi_col * 2 >> xd->plane[p].subsampling_x),
|
2013-07-23 15:51:44 +02:00
|
|
|
(sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide) >>
|
|
|
|
xd->plane[p].subsampling_x);
|
2013-06-19 23:26:49 +02:00
|
|
|
vpx_memcpy(
|
2013-07-23 15:51:44 +02:00
|
|
|
l + num_4x4_blocks_high * p,
|
2013-10-24 18:10:59 +02:00
|
|
|
cpi->left_context[p]
|
2013-07-23 15:51:44 +02:00
|
|
|
+ ((mi_row & MI_MASK) * 2 >> xd->plane[p].subsampling_y),
|
|
|
|
(sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high) >>
|
|
|
|
xd->plane[p].subsampling_y);
|
|
|
|
}
|
2013-10-24 18:10:59 +02:00
|
|
|
vpx_memcpy(sa, cpi->above_seg_context + mi_col,
|
|
|
|
sizeof(*cpi->above_seg_context) * mi_width);
|
|
|
|
vpx_memcpy(sl, cpi->left_seg_context + (mi_row & MI_MASK),
|
|
|
|
sizeof(cpi->left_seg_context[0]) * mi_height);
|
2013-07-23 15:51:44 +02:00
|
|
|
}
|
2013-05-08 23:24:43 +02:00
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
static void encode_b(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
2013-12-11 23:38:22 +01:00
|
|
|
int output_enabled, BLOCK_SIZE bsize) {
|
2013-11-12 00:58:57 +01:00
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize < BLOCK_8X8) {
|
2013-08-01 18:04:15 +02:00
|
|
|
// When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
|
|
|
|
// there is nothing to be done.
|
2013-11-12 00:58:57 +01:00
|
|
|
if (x->ab_index > 0)
|
2013-05-16 07:28:36 +02:00
|
|
|
return;
|
2013-08-01 18:04:15 +02:00
|
|
|
}
|
2013-10-25 17:18:04 +02:00
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, bsize);
|
2013-04-28 17:59:13 +02:00
|
|
|
update_state(cpi, get_block_context(x, bsize), bsize, output_enabled);
|
2013-05-05 07:09:43 +02:00
|
|
|
encode_superblock(cpi, tp, output_enabled, mi_row, mi_col, bsize);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-04-28 17:59:13 +02:00
|
|
|
if (output_enabled) {
|
2013-08-01 01:59:15 +02:00
|
|
|
update_stats(cpi);
|
2013-04-23 19:12:18 +02:00
|
|
|
|
2013-04-28 17:59:13 +02:00
|
|
|
(*tp)->token = EOSB_TOKEN;
|
|
|
|
(*tp)++;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
static void encode_sb(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
2013-08-27 20:05:08 +02:00
|
|
|
int output_enabled, BLOCK_SIZE bsize) {
|
2013-11-12 00:58:57 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
2013-12-11 23:38:22 +01:00
|
|
|
const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
|
|
|
|
int ctx;
|
2013-07-23 15:51:44 +02:00
|
|
|
PARTITION_TYPE partition;
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE subsize;
|
2013-04-23 19:12:18 +02:00
|
|
|
|
2013-04-28 17:59:13 +02:00
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
|
|
|
|
return;
|
2013-01-07 20:41:49 +01:00
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize >= BLOCK_8X8) {
|
2013-12-11 23:38:22 +01:00
|
|
|
ctx = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, bsize);
|
2013-12-11 23:38:22 +01:00
|
|
|
subsize = *get_sb_partitioning(x, bsize);
|
|
|
|
} else {
|
|
|
|
ctx = 0;
|
|
|
|
subsize = BLOCK_4X4;
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
2013-12-11 23:38:22 +01:00
|
|
|
|
|
|
|
partition = partition_lookup[bsl][subsize];
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-07-23 15:51:44 +02:00
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2013-08-06 00:23:49 +02:00
|
|
|
if (output_enabled && bsize >= BLOCK_8X8)
|
2013-12-11 23:38:22 +01:00
|
|
|
cm->counts.partition[ctx][PARTITION_NONE]++;
|
|
|
|
encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
|
2013-07-23 15:51:44 +02:00
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
|
|
|
if (output_enabled)
|
2013-12-11 23:38:22 +01:00
|
|
|
cm->counts.partition[ctx][PARTITION_VERT]++;
|
|
|
|
*get_sb_index(x, subsize) = 0;
|
|
|
|
encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
|
|
|
|
if (mi_col + hbs < cm->mi_cols) {
|
|
|
|
*get_sb_index(x, subsize) = 1;
|
|
|
|
encode_b(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize);
|
|
|
|
}
|
2013-07-23 15:51:44 +02:00
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
|
|
|
if (output_enabled)
|
2013-12-11 23:38:22 +01:00
|
|
|
cm->counts.partition[ctx][PARTITION_HORZ]++;
|
|
|
|
*get_sb_index(x, subsize) = 0;
|
|
|
|
encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
|
|
|
|
if (mi_row + hbs < cm->mi_rows) {
|
|
|
|
*get_sb_index(x, subsize) = 1;
|
|
|
|
encode_b(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize);
|
|
|
|
}
|
2013-07-23 15:51:44 +02:00
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
|
|
|
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
|
|
|
if (output_enabled)
|
2013-12-11 23:38:22 +01:00
|
|
|
cm->counts.partition[ctx][PARTITION_SPLIT]++;
|
|
|
|
|
|
|
|
*get_sb_index(x, subsize) = 0;
|
|
|
|
encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
|
|
|
|
*get_sb_index(x, subsize) = 1;
|
|
|
|
encode_sb(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize);
|
|
|
|
*get_sb_index(x, subsize) = 2;
|
|
|
|
encode_sb(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize);
|
|
|
|
*get_sb_index(x, subsize) = 3;
|
|
|
|
encode_sb(cpi, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled,
|
|
|
|
subsize);
|
2013-07-23 15:51:44 +02:00
|
|
|
break;
|
|
|
|
default:
|
2013-12-11 23:38:22 +01:00
|
|
|
assert("Invalid partition type.");
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
2013-04-23 19:12:18 +02:00
|
|
|
|
2013-10-21 21:02:19 +02:00
|
|
|
if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
|
2013-10-24 18:10:59 +02:00
|
|
|
update_partition_context(cpi->above_seg_context, cpi->left_seg_context,
|
2013-12-11 23:38:22 +01:00
|
|
|
mi_row, mi_col, subsize, bsize);
|
2012-04-07 01:38:34 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-08-31 01:39:26 +02:00
|
|
|
// Check to see if the given partition size is allowed for a specified number
|
|
|
|
// of 8x8 block rows and columns remaining in the image.
|
|
|
|
// If not then return the largest allowed partition size
|
|
|
|
static BLOCK_SIZE find_partition_size(BLOCK_SIZE bsize,
|
|
|
|
int rows_left, int cols_left,
|
|
|
|
int *bh, int *bw) {
|
2014-01-10 22:48:44 +01:00
|
|
|
if (rows_left <= 0 || cols_left <= 0) {
|
2013-08-31 01:39:26 +02:00
|
|
|
return MIN(bsize, BLOCK_8X8);
|
|
|
|
} else {
|
|
|
|
for (; bsize > 0; --bsize) {
|
|
|
|
*bh = num_8x8_blocks_high_lookup[bsize];
|
|
|
|
*bw = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
if ((*bh <= rows_left) && (*bw <= cols_left)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function attempts to set all mode info entries in a given SB64
|
|
|
|
// to the same block partition size.
|
|
|
|
// However, at the bottom and right borders of the image the requested size
|
|
|
|
// may not be allowed in which case this code attempts to choose the largest
|
|
|
|
// allowable partition.
|
2013-10-25 17:18:04 +02:00
|
|
|
static void set_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
MODE_INFO **mi_8x8, int mi_row, int mi_col) {
|
2013-06-20 16:46:51 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2013-08-31 01:39:26 +02:00
|
|
|
BLOCK_SIZE bsize = cpi->sf.always_this_block_size;
|
2013-05-31 00:13:08 +02:00
|
|
|
const int mis = cm->mode_info_stride;
|
2013-10-25 17:18:04 +02:00
|
|
|
int row8x8_remaining = tile->mi_row_end - mi_row;
|
|
|
|
int col8x8_remaining = tile->mi_col_end - mi_col;
|
2013-05-31 00:13:08 +02:00
|
|
|
int block_row, block_col;
|
2014-01-10 22:48:44 +01:00
|
|
|
MODE_INFO *mi_upper_left = cm->mi + mi_row * mis + mi_col;
|
2013-09-11 19:45:44 +02:00
|
|
|
int bh = num_8x8_blocks_high_lookup[bsize];
|
|
|
|
int bw = num_8x8_blocks_wide_lookup[bsize];
|
2013-08-31 01:39:26 +02:00
|
|
|
|
|
|
|
assert((row8x8_remaining > 0) && (col8x8_remaining > 0));
|
|
|
|
|
|
|
|
// Apply the requested partition size to the SB64 if it is all "in image"
|
|
|
|
if ((col8x8_remaining >= MI_BLOCK_SIZE) &&
|
|
|
|
(row8x8_remaining >= MI_BLOCK_SIZE)) {
|
2013-09-11 19:45:44 +02:00
|
|
|
for (block_row = 0; block_row < MI_BLOCK_SIZE; block_row += bh) {
|
|
|
|
for (block_col = 0; block_col < MI_BLOCK_SIZE; block_col += bw) {
|
|
|
|
int index = block_row * mis + block_col;
|
|
|
|
mi_8x8[index] = mi_upper_left + index;
|
|
|
|
mi_8x8[index]->mbmi.sb_type = bsize;
|
2013-08-31 01:39:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Else this is a partial SB64.
|
|
|
|
for (block_row = 0; block_row < MI_BLOCK_SIZE; block_row += bh) {
|
|
|
|
for (block_col = 0; block_col < MI_BLOCK_SIZE; block_col += bw) {
|
2013-09-11 19:45:44 +02:00
|
|
|
int index = block_row * mis + block_col;
|
2013-08-31 01:39:26 +02:00
|
|
|
// Find a partition size that fits
|
|
|
|
bsize = find_partition_size(cpi->sf.always_this_block_size,
|
|
|
|
(row8x8_remaining - block_row),
|
|
|
|
(col8x8_remaining - block_col), &bh, &bw);
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_8x8[index] = mi_upper_left + index;
|
|
|
|
mi_8x8[index]->mbmi.sb_type = bsize;
|
2013-08-31 01:39:26 +02:00
|
|
|
}
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-11 19:45:44 +02:00
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
static void copy_partitioning(VP9_COMMON *cm, MODE_INFO **mi_8x8,
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO **prev_mi_8x8) {
|
2013-06-20 18:32:19 +02:00
|
|
|
const int mis = cm->mode_info_stride;
|
|
|
|
int block_row, block_col;
|
2013-09-11 19:45:44 +02:00
|
|
|
|
2013-06-20 18:32:19 +02:00
|
|
|
for (block_row = 0; block_row < 8; ++block_row) {
|
|
|
|
for (block_col = 0; block_col < 8; ++block_col) {
|
2014-01-10 22:48:44 +01:00
|
|
|
MODE_INFO *const prev_mi = prev_mi_8x8[block_row * mis + block_col];
|
|
|
|
const BLOCK_SIZE sb_type = prev_mi ? prev_mi->mbmi.sb_type : 0;
|
2013-09-11 19:45:44 +02:00
|
|
|
if (prev_mi) {
|
2014-01-10 22:48:44 +01:00
|
|
|
const ptrdiff_t offset = prev_mi - cm->prev_mi;
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_8x8[block_row * mis + block_col] = cm->mi + offset;
|
|
|
|
mi_8x8[block_row * mis + block_col]->mbmi.sb_type = sb_type;
|
|
|
|
}
|
2013-06-20 18:32:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-05-31 00:13:08 +02:00
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
static int sb_has_motion(const VP9_COMMON *cm, MODE_INFO **prev_mi_8x8) {
|
2013-07-08 15:13:48 +02:00
|
|
|
const int mis = cm->mode_info_stride;
|
|
|
|
int block_row, block_col;
|
|
|
|
|
|
|
|
if (cm->prev_mi) {
|
|
|
|
for (block_row = 0; block_row < 8; ++block_row) {
|
|
|
|
for (block_col = 0; block_col < 8; ++block_col) {
|
2014-01-10 22:48:44 +01:00
|
|
|
const MODE_INFO *prev_mi = prev_mi_8x8[block_row * mis + block_col];
|
2013-07-08 15:13:48 +02:00
|
|
|
if (prev_mi) {
|
|
|
|
if (abs(prev_mi->mbmi.mv[0].as_mv.row) >= 8 ||
|
|
|
|
abs(prev_mi->mbmi.mv[0].as_mv.col) >= 8)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2014-01-29 17:39:39 +01:00
|
|
|
static void update_state_rt(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
|
|
|
|
BLOCK_SIZE bsize, int output_enabled) {
|
|
|
|
int i;
|
2014-01-10 20:51:20 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
2014-01-29 17:39:39 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
|
|
|
struct macroblock_plane *const p = x->plane;
|
|
|
|
struct macroblockd_plane *const pd = xd->plane;
|
|
|
|
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
2014-01-10 20:51:20 +01:00
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
const int mb_mode_index = ctx->best_mode_index;
|
|
|
|
int max_plane;
|
2014-01-10 20:51:20 +01:00
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
max_plane = is_inter_block(mbmi) ? MAX_MB_PLANE : 1;
|
|
|
|
for (i = 0; i < max_plane; ++i) {
|
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][1];
|
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][1];
|
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][1];
|
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][1];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = max_plane; i < MAX_MB_PLANE; ++i) {
|
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][2];
|
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][2];
|
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][2];
|
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][2];
|
|
|
|
}
|
|
|
|
|
|
|
|
x->skip = ctx->skip;
|
|
|
|
|
|
|
|
if (frame_is_intra_only(cm)) {
|
|
|
|
#if CONFIG_INTERNAL_STATS
|
|
|
|
static const int kf_mode_index[] = {
|
|
|
|
THR_DC /*DC_PRED*/,
|
|
|
|
THR_V_PRED /*V_PRED*/,
|
|
|
|
THR_H_PRED /*H_PRED*/,
|
|
|
|
THR_D45_PRED /*D45_PRED*/,
|
|
|
|
THR_D135_PRED /*D135_PRED*/,
|
|
|
|
THR_D117_PRED /*D117_PRED*/,
|
|
|
|
THR_D153_PRED /*D153_PRED*/,
|
|
|
|
THR_D207_PRED /*D207_PRED*/,
|
|
|
|
THR_D63_PRED /*D63_PRED*/,
|
|
|
|
THR_TM /*TM_PRED*/,
|
|
|
|
};
|
2014-01-30 03:15:37 +01:00
|
|
|
++cpi->mode_chosen_counts[kf_mode_index[mbmi->mode]];
|
2014-01-29 17:39:39 +01:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
// Note how often each mode chosen as best
|
|
|
|
cpi->mode_chosen_counts[mb_mode_index]++;
|
|
|
|
if (is_inter_block(mbmi) &&
|
|
|
|
(mbmi->sb_type < BLOCK_8X8 || mbmi->mode == NEWMV)) {
|
|
|
|
int_mv best_mv[2];
|
|
|
|
for (i = 0; i < 1 + has_second_ref(mbmi); ++i)
|
|
|
|
best_mv[i].as_int = mbmi->ref_mvs[mbmi->ref_frame[i]][0].as_int;
|
|
|
|
vp9_update_mv_count(cpi, x, best_mv);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cm->interp_filter == SWITCHABLE && is_inter_mode(mbmi->mode)) {
|
|
|
|
const int ctx = vp9_get_pred_context_switchable_interp(xd);
|
|
|
|
++cm->counts.switchable_interp[ctx][mbmi->interp_filter];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void encode_b_rt(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
|
|
|
int output_enabled, BLOCK_SIZE bsize) {
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
2014-01-10 20:51:20 +01:00
|
|
|
|
|
|
|
if (bsize < BLOCK_8X8) {
|
|
|
|
// When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
|
|
|
|
// there is nothing to be done.
|
2014-01-29 17:39:39 +01:00
|
|
|
if (x->ab_index > 0)
|
2014-01-10 20:51:20 +01:00
|
|
|
return;
|
2014-01-29 17:39:39 +01:00
|
|
|
}
|
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, bsize);
|
|
|
|
update_state_rt(cpi, get_block_context(x, bsize), bsize, output_enabled);
|
|
|
|
|
|
|
|
encode_superblock(cpi, tp, output_enabled, mi_row, mi_col, bsize);
|
|
|
|
update_stats(cpi);
|
|
|
|
|
|
|
|
(*tp)->token = EOSB_TOKEN;
|
|
|
|
(*tp)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void encode_sb_rt(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
|
|
|
int output_enabled, BLOCK_SIZE bsize) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
|
|
|
|
int ctx;
|
|
|
|
PARTITION_TYPE partition;
|
|
|
|
BLOCK_SIZE subsize;
|
|
|
|
|
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (bsize >= BLOCK_8X8) {
|
|
|
|
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
|
|
|
const int idx_str = xd->mode_info_stride * mi_row + mi_col;
|
|
|
|
MODE_INFO ** mi_8x8 = cm->mi_grid_visible + idx_str;
|
|
|
|
ctx = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
|
|
|
|
mi_row, mi_col, bsize);
|
|
|
|
subsize = mi_8x8[0]->mbmi.sb_type;
|
|
|
|
|
2014-01-10 20:51:20 +01:00
|
|
|
} else {
|
2014-01-29 17:39:39 +01:00
|
|
|
ctx = 0;
|
|
|
|
subsize = BLOCK_4X4;
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
partition = partition_lookup[bsl][subsize];
|
|
|
|
|
2014-01-10 20:51:20 +01:00
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2014-01-29 17:39:39 +01:00
|
|
|
if (output_enabled && bsize >= BLOCK_8X8)
|
|
|
|
cm->counts.partition[ctx][PARTITION_NONE]++;
|
|
|
|
encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
|
2014-01-10 20:51:20 +01:00
|
|
|
break;
|
2014-01-29 17:39:39 +01:00
|
|
|
case PARTITION_VERT:
|
|
|
|
if (output_enabled)
|
|
|
|
cm->counts.partition[ctx][PARTITION_VERT]++;
|
2014-01-10 20:51:20 +01:00
|
|
|
*get_sb_index(x, subsize) = 0;
|
2014-01-29 17:39:39 +01:00
|
|
|
encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
|
|
|
|
if (mi_col + hbs < cm->mi_cols) {
|
2014-01-10 20:51:20 +01:00
|
|
|
*get_sb_index(x, subsize) = 1;
|
2014-01-29 17:39:39 +01:00
|
|
|
encode_b_rt(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled,
|
|
|
|
subsize);
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
break;
|
2014-01-29 17:39:39 +01:00
|
|
|
case PARTITION_HORZ:
|
|
|
|
if (output_enabled)
|
|
|
|
cm->counts.partition[ctx][PARTITION_HORZ]++;
|
2014-01-10 20:51:20 +01:00
|
|
|
*get_sb_index(x, subsize) = 0;
|
2014-01-29 17:39:39 +01:00
|
|
|
encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
|
|
|
|
if (mi_row + hbs < cm->mi_rows) {
|
2014-01-10 20:51:20 +01:00
|
|
|
*get_sb_index(x, subsize) = 1;
|
2014-01-29 17:39:39 +01:00
|
|
|
encode_b_rt(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled,
|
|
|
|
subsize);
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
2014-01-29 17:39:39 +01:00
|
|
|
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
|
|
|
if (output_enabled)
|
|
|
|
cm->counts.partition[ctx][PARTITION_SPLIT]++;
|
2014-01-10 20:51:20 +01:00
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
*get_sb_index(x, subsize) = 0;
|
|
|
|
encode_sb_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
|
|
|
|
*get_sb_index(x, subsize) = 1;
|
|
|
|
encode_sb_rt(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled,
|
|
|
|
subsize);
|
|
|
|
*get_sb_index(x, subsize) = 2;
|
|
|
|
encode_sb_rt(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled,
|
|
|
|
subsize);
|
|
|
|
*get_sb_index(x, subsize) = 3;
|
|
|
|
encode_sb_rt(cpi, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled,
|
|
|
|
subsize);
|
2014-01-10 20:51:20 +01:00
|
|
|
break;
|
|
|
|
default:
|
2014-01-29 17:39:39 +01:00
|
|
|
assert("Invalid partition type.");
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
|
|
|
|
update_partition_context(cpi->above_seg_context, cpi->left_seg_context,
|
|
|
|
mi_row, mi_col, subsize, bsize);
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
static void rd_use_partition(VP9_COMP *cpi,
|
|
|
|
const TileInfo *const tile,
|
|
|
|
MODE_INFO **mi_8x8,
|
2013-09-11 19:45:44 +02:00
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
|
|
|
BLOCK_SIZE bsize, int *rate, int64_t *dist,
|
|
|
|
int do_recon) {
|
2013-11-12 00:58:57 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
2013-05-31 00:13:08 +02:00
|
|
|
const int mis = cm->mode_info_stride;
|
2014-01-10 22:48:44 +01:00
|
|
|
const int bsl = b_width_log2(bsize);
|
2013-08-05 21:15:52 +02:00
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
|
2014-01-10 22:48:44 +01:00
|
|
|
const int ms = num_4x4_blocks_wide / 2;
|
|
|
|
const int mh = num_4x4_blocks_high / 2;
|
|
|
|
const int bss = (1 << bsl) / 4;
|
2013-05-31 00:13:08 +02:00
|
|
|
int i, pl;
|
2013-07-10 23:27:20 +02:00
|
|
|
PARTITION_TYPE partition = PARTITION_NONE;
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE subsize;
|
2013-05-31 00:13:08 +02:00
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
|
|
|
|
PARTITION_CONTEXT sl[8], sa[8];
|
2013-07-02 03:18:50 +02:00
|
|
|
int last_part_rate = INT_MAX;
|
|
|
|
int64_t last_part_dist = INT_MAX;
|
|
|
|
int split_rate = INT_MAX;
|
|
|
|
int64_t split_dist = INT_MAX;
|
|
|
|
int none_rate = INT_MAX;
|
|
|
|
int64_t none_dist = INT_MAX;
|
|
|
|
int chosen_rate = INT_MAX;
|
|
|
|
int64_t chosen_dist = INT_MAX;
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE sub_subsize = BLOCK_4X4;
|
2013-07-02 03:18:50 +02:00
|
|
|
int splits_below = 0;
|
2013-09-11 19:45:44 +02:00
|
|
|
BLOCK_SIZE bs_type = mi_8x8[0]->mbmi.sb_type;
|
2013-05-31 00:13:08 +02:00
|
|
|
|
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
|
|
|
|
return;
|
|
|
|
|
2013-07-23 15:51:44 +02:00
|
|
|
partition = partition_lookup[bsl][bs_type];
|
2013-05-31 00:13:08 +02:00
|
|
|
subsize = get_subsize(bsize, partition);
|
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize < BLOCK_8X8) {
|
2013-08-01 18:04:15 +02:00
|
|
|
// When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
|
|
|
|
// there is nothing to be done.
|
2013-11-12 00:58:57 +01:00
|
|
|
if (x->ab_index != 0) {
|
2013-06-20 18:32:19 +02:00
|
|
|
*rate = 0;
|
|
|
|
*dist = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2013-05-31 00:13:08 +02:00
|
|
|
*(get_sb_partitioning(x, bsize)) = subsize;
|
|
|
|
}
|
|
|
|
save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
if (bsize == BLOCK_16X16) {
|
2013-10-25 17:18:04 +02:00
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, bsize);
|
2013-10-07 20:20:10 +02:00
|
|
|
x->mb_energy = vp9_block_energy(cpi, x, bsize);
|
|
|
|
}
|
|
|
|
|
2013-07-25 19:28:38 +02:00
|
|
|
x->fast_ms = 0;
|
|
|
|
x->subblock_ref = 0;
|
|
|
|
|
2013-07-02 03:18:50 +02:00
|
|
|
if (cpi->sf.adjust_partitioning_from_last_frame) {
|
|
|
|
// Check if any of the sub blocks are further split.
|
2013-08-06 00:23:49 +02:00
|
|
|
if (partition == PARTITION_SPLIT && subsize > BLOCK_8X8) {
|
2013-07-02 03:18:50 +02:00
|
|
|
sub_subsize = get_subsize(subsize, PARTITION_SPLIT);
|
|
|
|
splits_below = 1;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
int jj = i >> 1, ii = i & 0x01;
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO * this_mi = mi_8x8[jj * bss * mis + ii * bss];
|
|
|
|
if (this_mi && this_mi->mbmi.sb_type >= sub_subsize) {
|
2013-07-02 03:18:50 +02:00
|
|
|
splits_below = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If partition is not none try none unless each of the 4 splits are split
|
|
|
|
// even further..
|
|
|
|
if (partition != PARTITION_NONE && !splits_below &&
|
|
|
|
mi_row + (ms >> 1) < cm->mi_rows &&
|
|
|
|
mi_col + (ms >> 1) < cm->mi_cols) {
|
|
|
|
*(get_sb_partitioning(x, bsize)) = bsize;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &none_rate, &none_dist, bsize,
|
|
|
|
get_block_context(x, bsize), INT64_MAX);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context,
|
|
|
|
cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, bsize);
|
2013-07-02 03:18:50 +02:00
|
|
|
none_rate += x->partition_cost[pl][PARTITION_NONE];
|
|
|
|
|
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_8x8[0]->mbmi.sb_type = bs_type;
|
2013-07-02 03:18:50 +02:00
|
|
|
*(get_sb_partitioning(x, bsize)) = subsize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 00:13:08 +02:00
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate,
|
|
|
|
&last_part_dist, bsize,
|
|
|
|
get_block_context(x, bsize), INT64_MAX);
|
2013-05-31 00:13:08 +02:00
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = 0;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate,
|
|
|
|
&last_part_dist, subsize,
|
|
|
|
get_block_context(x, subsize), INT64_MAX);
|
2013-07-22 15:39:39 +02:00
|
|
|
if (last_part_rate != INT_MAX &&
|
2013-08-06 00:23:49 +02:00
|
|
|
bsize >= BLOCK_8X8 && mi_row + (mh >> 1) < cm->mi_rows) {
|
2013-07-01 17:54:50 +02:00
|
|
|
int rt = 0;
|
|
|
|
int64_t dt = 0;
|
2013-05-31 00:13:08 +02:00
|
|
|
update_state(cpi, get_block_context(x, subsize), subsize, 0);
|
|
|
|
encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = 1;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row + (ms >> 1), mi_col, &rt, &dt,
|
|
|
|
subsize, get_block_context(x, subsize), INT64_MAX);
|
2013-07-22 15:39:39 +02:00
|
|
|
if (rt == INT_MAX || dt == INT_MAX) {
|
|
|
|
last_part_rate = INT_MAX;
|
|
|
|
last_part_dist = INT_MAX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-07-02 03:18:50 +02:00
|
|
|
last_part_rate += rt;
|
|
|
|
last_part_dist += dt;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = 0;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate,
|
|
|
|
&last_part_dist, subsize,
|
|
|
|
get_block_context(x, subsize), INT64_MAX);
|
2013-07-22 15:39:39 +02:00
|
|
|
if (last_part_rate != INT_MAX &&
|
2013-08-06 00:23:49 +02:00
|
|
|
bsize >= BLOCK_8X8 && mi_col + (ms >> 1) < cm->mi_cols) {
|
2013-07-01 17:54:50 +02:00
|
|
|
int rt = 0;
|
|
|
|
int64_t dt = 0;
|
2013-05-31 00:13:08 +02:00
|
|
|
update_state(cpi, get_block_context(x, subsize), subsize, 0);
|
|
|
|
encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = 1;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col + (ms >> 1), &rt, &dt,
|
|
|
|
subsize, get_block_context(x, subsize), INT64_MAX);
|
2013-07-22 15:39:39 +02:00
|
|
|
if (rt == INT_MAX || dt == INT_MAX) {
|
|
|
|
last_part_rate = INT_MAX;
|
|
|
|
last_part_dist = INT_MAX;
|
|
|
|
break;
|
|
|
|
}
|
2013-07-02 03:18:50 +02:00
|
|
|
last_part_rate += rt;
|
|
|
|
last_part_dist += dt;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
2013-07-02 03:18:50 +02:00
|
|
|
// Split partition.
|
|
|
|
last_part_rate = 0;
|
|
|
|
last_part_dist = 0;
|
2013-05-31 00:13:08 +02:00
|
|
|
for (i = 0; i < 4; i++) {
|
2013-07-02 03:18:50 +02:00
|
|
|
int x_idx = (i & 1) * (ms >> 1);
|
|
|
|
int y_idx = (i >> 1) * (ms >> 1);
|
2013-05-31 00:13:08 +02:00
|
|
|
int jj = i >> 1, ii = i & 0x01;
|
2013-07-02 03:18:50 +02:00
|
|
|
int rt;
|
|
|
|
int64_t dt;
|
2013-05-31 00:13:08 +02:00
|
|
|
|
|
|
|
if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
|
|
|
|
continue;
|
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = i;
|
2013-05-31 00:13:08 +02:00
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
rd_use_partition(cpi, tile, mi_8x8 + jj * bss * mis + ii * bss, tp,
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_row + y_idx, mi_col + x_idx, subsize, &rt, &dt,
|
|
|
|
i != 3);
|
2013-07-20 02:38:55 +02:00
|
|
|
if (rt == INT_MAX || dt == INT_MAX) {
|
|
|
|
last_part_rate = INT_MAX;
|
|
|
|
last_part_dist = INT_MAX;
|
|
|
|
break;
|
|
|
|
}
|
2013-07-02 03:18:50 +02:00
|
|
|
last_part_rate += rt;
|
|
|
|
last_part_dist += dt;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
}
|
2013-10-21 21:02:19 +02:00
|
|
|
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, bsize);
|
2013-07-20 02:38:55 +02:00
|
|
|
if (last_part_rate < INT_MAX)
|
|
|
|
last_part_rate += x->partition_cost[pl][partition];
|
|
|
|
|
2013-07-02 03:18:50 +02:00
|
|
|
if (cpi->sf.adjust_partitioning_from_last_frame
|
2013-08-06 00:23:49 +02:00
|
|
|
&& partition != PARTITION_SPLIT && bsize > BLOCK_8X8
|
2013-07-02 03:18:50 +02:00
|
|
|
&& (mi_row + ms < cm->mi_rows || mi_row + (ms >> 1) == cm->mi_rows)
|
|
|
|
&& (mi_col + ms < cm->mi_cols || mi_col + (ms >> 1) == cm->mi_cols)) {
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE split_subsize = get_subsize(bsize, PARTITION_SPLIT);
|
2013-07-02 03:18:50 +02:00
|
|
|
split_rate = 0;
|
|
|
|
split_dist = 0;
|
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
|
|
|
|
|
|
|
// Split partition.
|
|
|
|
for (i = 0; i < 4; i++) {
|
2013-07-23 15:51:44 +02:00
|
|
|
int x_idx = (i & 1) * (num_4x4_blocks_wide >> 2);
|
|
|
|
int y_idx = (i >> 1) * (num_4x4_blocks_wide >> 2);
|
2013-07-02 03:18:50 +02:00
|
|
|
int rt = 0;
|
|
|
|
int64_t dt = 0;
|
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
|
|
|
|
PARTITION_CONTEXT sl[8], sa[8];
|
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
|
2013-07-02 03:18:50 +02:00
|
|
|
continue;
|
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, split_subsize) = i;
|
2013-08-28 21:22:37 +02:00
|
|
|
*get_sb_partitioning(x, bsize) = split_subsize;
|
|
|
|
*get_sb_partitioning(x, split_subsize) = split_subsize;
|
2013-07-02 03:18:50 +02:00
|
|
|
|
|
|
|
save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
|
|
|
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row + y_idx, mi_col + x_idx, &rt, &dt,
|
|
|
|
split_subsize, get_block_context(x, split_subsize),
|
|
|
|
INT64_MAX);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
|
|
|
|
2013-07-22 15:39:39 +02:00
|
|
|
if (rt == INT_MAX || dt == INT_MAX) {
|
|
|
|
split_rate = INT_MAX;
|
|
|
|
split_dist = INT_MAX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i != 3)
|
2013-10-25 17:18:04 +02:00
|
|
|
encode_sb(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx, 0,
|
2013-07-02 03:18:50 +02:00
|
|
|
split_subsize);
|
|
|
|
|
|
|
|
split_rate += rt;
|
|
|
|
split_dist += dt;
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context,
|
|
|
|
cpi->left_seg_context,
|
2013-12-10 23:34:32 +01:00
|
|
|
mi_row + y_idx, mi_col + x_idx,
|
|
|
|
split_subsize);
|
2013-07-02 03:18:50 +02:00
|
|
|
split_rate += x->partition_cost[pl][PARTITION_NONE];
|
|
|
|
}
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, bsize);
|
2013-07-22 15:39:39 +02:00
|
|
|
if (split_rate < INT_MAX) {
|
|
|
|
split_rate += x->partition_cost[pl][PARTITION_SPLIT];
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2013-07-22 15:39:39 +02:00
|
|
|
chosen_rate = split_rate;
|
|
|
|
chosen_dist = split_dist;
|
|
|
|
}
|
2013-07-02 03:18:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// If last_part is better set the partitioning to that...
|
|
|
|
if (RDCOST(x->rdmult, x->rddiv, last_part_rate, last_part_dist)
|
|
|
|
< RDCOST(x->rdmult, x->rddiv, chosen_rate, chosen_dist)) {
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_8x8[0]->mbmi.sb_type = bsize;
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize >= BLOCK_8X8)
|
2013-07-02 03:18:50 +02:00
|
|
|
*(get_sb_partitioning(x, bsize)) = subsize;
|
|
|
|
chosen_rate = last_part_rate;
|
|
|
|
chosen_dist = last_part_dist;
|
|
|
|
}
|
|
|
|
// If none was better set the partitioning to that...
|
|
|
|
if (RDCOST(x->rdmult, x->rddiv, chosen_rate, chosen_dist)
|
|
|
|
> RDCOST(x->rdmult, x->rddiv, none_rate, none_dist)) {
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize >= BLOCK_8X8)
|
2013-07-02 03:18:50 +02:00
|
|
|
*(get_sb_partitioning(x, bsize)) = bsize;
|
|
|
|
chosen_rate = none_rate;
|
|
|
|
chosen_dist = none_dist;
|
|
|
|
}
|
2013-05-31 00:13:08 +02:00
|
|
|
|
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
|
|
|
|
2013-07-02 03:18:50 +02:00
|
|
|
// We must have chosen a partitioning and encoding or we'll fail later on.
|
|
|
|
// No other opportunities for success.
|
2013-08-06 00:23:49 +02:00
|
|
|
if ( bsize == BLOCK_64X64)
|
2013-07-20 02:38:55 +02:00
|
|
|
assert(chosen_rate < INT_MAX && chosen_dist < INT_MAX);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2013-11-22 18:21:53 +01:00
|
|
|
if (do_recon) {
|
|
|
|
int output_enabled = (bsize == BLOCK_64X64);
|
|
|
|
|
|
|
|
// Check the projected output rate for this SB against it's target
|
|
|
|
// and and if necessary apply a Q delta using segmentation to get
|
|
|
|
// closer to the target.
|
|
|
|
if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
|
|
|
|
select_in_frame_q_segment(cpi, mi_row, mi_col,
|
|
|
|
output_enabled, chosen_rate);
|
|
|
|
}
|
|
|
|
|
|
|
|
encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, bsize);
|
|
|
|
}
|
2013-07-20 02:38:55 +02:00
|
|
|
|
2013-07-02 03:18:50 +02:00
|
|
|
*rate = chosen_rate;
|
|
|
|
*dist = chosen_dist;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
|
2013-08-27 20:05:08 +02:00
|
|
|
static const BLOCK_SIZE min_partition_size[BLOCK_SIZES] = {
|
2014-01-29 19:03:07 +01:00
|
|
|
BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
|
|
|
|
BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
|
|
|
|
BLOCK_8X8, BLOCK_8X8, BLOCK_8X8,
|
|
|
|
BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,
|
|
|
|
BLOCK_16X16
|
2013-08-27 20:05:08 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const BLOCK_SIZE max_partition_size[BLOCK_SIZES] = {
|
2014-01-29 19:03:07 +01:00
|
|
|
BLOCK_8X8, BLOCK_16X16, BLOCK_16X16,
|
|
|
|
BLOCK_16X16, BLOCK_32X32, BLOCK_32X32,
|
|
|
|
BLOCK_32X32, BLOCK_64X64, BLOCK_64X64,
|
|
|
|
BLOCK_64X64, BLOCK_64X64, BLOCK_64X64,
|
|
|
|
BLOCK_64X64
|
2013-08-27 20:05:08 +02:00
|
|
|
};
|
2013-07-24 15:07:37 +02:00
|
|
|
|
2013-08-16 17:54:12 +02:00
|
|
|
// Look at all the mode_info entries for blocks that are part of this
|
|
|
|
// partition and find the min and max values for sb_type.
|
|
|
|
// At the moment this is designed to work on a 64x64 SB but could be
|
|
|
|
// adjusted to use a size parameter.
|
|
|
|
//
|
|
|
|
// The min and max are assumed to have been initialized prior to calling this
|
|
|
|
// function so repeat calls can accumulate a min and max of more than one sb64.
|
2013-09-11 19:45:44 +02:00
|
|
|
static void get_sb_partition_size_range(VP9_COMP *cpi, MODE_INFO ** mi_8x8,
|
|
|
|
BLOCK_SIZE * min_block_size,
|
|
|
|
BLOCK_SIZE * max_block_size ) {
|
2013-08-16 17:54:12 +02:00
|
|
|
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
|
|
|
int sb_width_in_blocks = MI_BLOCK_SIZE;
|
|
|
|
int sb_height_in_blocks = MI_BLOCK_SIZE;
|
|
|
|
int i, j;
|
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
// Check the sb_type for each block that belongs to this region.
|
|
|
|
for (i = 0; i < sb_height_in_blocks; ++i) {
|
|
|
|
for (j = 0; j < sb_width_in_blocks; ++j) {
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO * mi = mi_8x8[index+j];
|
|
|
|
BLOCK_SIZE sb_type = mi ? mi->mbmi.sb_type : 0;
|
|
|
|
*min_block_size = MIN(*min_block_size, sb_type);
|
|
|
|
*max_block_size = MAX(*max_block_size, sb_type);
|
2013-08-16 17:54:12 +02:00
|
|
|
}
|
|
|
|
index += xd->mode_info_stride;
|
|
|
|
}
|
|
|
|
}
|
2013-07-24 15:07:37 +02:00
|
|
|
|
2013-08-01 18:04:15 +02:00
|
|
|
// Look at neighboring blocks and set a min and max partition size based on
|
2013-07-24 15:07:37 +02:00
|
|
|
// what they chose.
|
2013-10-25 17:18:04 +02:00
|
|
|
static void rd_auto_partition_range(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
int row, int col,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE *min_block_size,
|
|
|
|
BLOCK_SIZE *max_block_size) {
|
2013-09-27 13:59:06 +02:00
|
|
|
VP9_COMMON * const cm = &cpi->common;
|
2013-07-24 15:07:37 +02:00
|
|
|
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO ** mi_8x8 = xd->mi_8x8;
|
2013-09-27 13:59:06 +02:00
|
|
|
MODE_INFO ** prev_mi_8x8 = xd->prev_mi_8x8;
|
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
const int left_in_image = xd->left_available && mi_8x8[-1];
|
|
|
|
const int above_in_image = xd->up_available &&
|
|
|
|
mi_8x8[-xd->mode_info_stride];
|
|
|
|
MODE_INFO ** above_sb64_mi_8x8;
|
|
|
|
MODE_INFO ** left_sb64_mi_8x8;
|
2013-07-24 15:07:37 +02:00
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
int row8x8_remaining = tile->mi_row_end - row;
|
|
|
|
int col8x8_remaining = tile->mi_col_end - col;
|
2013-09-27 13:59:06 +02:00
|
|
|
int bh, bw;
|
|
|
|
|
|
|
|
// Trap case where we do not have a prediction.
|
|
|
|
if (!left_in_image && !above_in_image &&
|
|
|
|
((cm->frame_type == KEY_FRAME) || !cm->prev_mi)) {
|
2013-07-24 15:07:37 +02:00
|
|
|
*min_block_size = BLOCK_4X4;
|
|
|
|
*max_block_size = BLOCK_64X64;
|
|
|
|
} else {
|
2013-09-27 13:59:06 +02:00
|
|
|
// Default "min to max" and "max to min"
|
|
|
|
*min_block_size = BLOCK_64X64;
|
|
|
|
*max_block_size = BLOCK_4X4;
|
|
|
|
|
|
|
|
// NOTE: each call to get_sb_partition_size_range() uses the previous
|
|
|
|
// passed in values for min and max as a starting point.
|
|
|
|
//
|
|
|
|
// Find the min and max partition used in previous frame at this location
|
|
|
|
if (cm->prev_mi && (cm->frame_type != KEY_FRAME)) {
|
|
|
|
get_sb_partition_size_range(cpi, prev_mi_8x8,
|
|
|
|
min_block_size, max_block_size);
|
|
|
|
}
|
2013-09-04 00:46:22 +02:00
|
|
|
|
2013-09-27 13:59:06 +02:00
|
|
|
// Find the min and max partition sizes used in the left SB64
|
|
|
|
if (left_in_image) {
|
|
|
|
left_sb64_mi_8x8 = &mi_8x8[-MI_BLOCK_SIZE];
|
|
|
|
get_sb_partition_size_range(cpi, left_sb64_mi_8x8,
|
|
|
|
min_block_size, max_block_size);
|
|
|
|
}
|
2013-08-16 17:54:12 +02:00
|
|
|
|
2013-09-27 13:59:06 +02:00
|
|
|
// Find the min and max partition sizes used in the above SB64.
|
|
|
|
if (above_in_image) {
|
|
|
|
above_sb64_mi_8x8 = &mi_8x8[-xd->mode_info_stride * MI_BLOCK_SIZE];
|
|
|
|
get_sb_partition_size_range(cpi, above_sb64_mi_8x8,
|
|
|
|
min_block_size, max_block_size);
|
2013-09-04 00:46:22 +02:00
|
|
|
}
|
2013-07-24 15:07:37 +02:00
|
|
|
}
|
2013-09-27 13:59:06 +02:00
|
|
|
|
2014-01-29 19:03:07 +01:00
|
|
|
// adjust observed min and max
|
|
|
|
if (cpi->sf.auto_min_max_partition_size == RELAXED_NEIGHBORING_MIN_MAX) {
|
|
|
|
*min_block_size = min_partition_size[*min_block_size];
|
|
|
|
*max_block_size = max_partition_size[*max_block_size];
|
|
|
|
}
|
2013-09-27 13:59:06 +02:00
|
|
|
|
|
|
|
// Check border cases where max and min from neighbours may not be legal.
|
|
|
|
*max_block_size = find_partition_size(*max_block_size,
|
|
|
|
row8x8_remaining, col8x8_remaining,
|
|
|
|
&bh, &bw);
|
|
|
|
*min_block_size = MIN(*min_block_size, *max_block_size);
|
2013-07-24 15:07:37 +02:00
|
|
|
}
|
2013-05-08 23:24:43 +02:00
|
|
|
|
2013-08-27 20:05:08 +02:00
|
|
|
static void compute_fast_motion_search_level(VP9_COMP *cpi, BLOCK_SIZE bsize) {
|
2013-08-03 02:19:29 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
|
|
|
|
// Only use 8x8 result for non HD videos.
|
|
|
|
// int use_8x8 = (MIN(cpi->common.width, cpi->common.height) < 720) ? 1 : 0;
|
|
|
|
int use_8x8 = 1;
|
|
|
|
|
2013-12-13 18:32:05 +01:00
|
|
|
if (cm->frame_type && !cpi->rc.is_src_frame_alt_ref &&
|
2013-08-03 02:19:29 +02:00
|
|
|
((use_8x8 && bsize == BLOCK_16X16) ||
|
|
|
|
bsize == BLOCK_32X32 || bsize == BLOCK_64X64)) {
|
|
|
|
int ref0 = 0, ref1 = 0, ref2 = 0, ref3 = 0;
|
|
|
|
PICK_MODE_CONTEXT *block_context = NULL;
|
|
|
|
|
|
|
|
if (bsize == BLOCK_16X16) {
|
2013-11-12 00:58:57 +01:00
|
|
|
block_context = x->sb8x8_context[x->sb_index][x->mb_index];
|
2013-08-03 02:19:29 +02:00
|
|
|
} else if (bsize == BLOCK_32X32) {
|
2013-11-12 00:58:57 +01:00
|
|
|
block_context = x->mb_context[x->sb_index];
|
2013-08-03 02:19:29 +02:00
|
|
|
} else if (bsize == BLOCK_64X64) {
|
|
|
|
block_context = x->sb32_context;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (block_context) {
|
|
|
|
ref0 = block_context[0].mic.mbmi.ref_frame[0];
|
|
|
|
ref1 = block_context[1].mic.mbmi.ref_frame[0];
|
|
|
|
ref2 = block_context[2].mic.mbmi.ref_frame[0];
|
|
|
|
ref3 = block_context[3].mic.mbmi.ref_frame[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Currently, only consider 4 inter reference frames.
|
|
|
|
if (ref0 && ref1 && ref2 && ref3) {
|
|
|
|
int d01, d23, d02, d13;
|
|
|
|
|
|
|
|
// Motion vectors for the four subblocks.
|
|
|
|
int16_t mvr0 = block_context[0].mic.mbmi.mv[0].as_mv.row;
|
|
|
|
int16_t mvc0 = block_context[0].mic.mbmi.mv[0].as_mv.col;
|
|
|
|
int16_t mvr1 = block_context[1].mic.mbmi.mv[0].as_mv.row;
|
|
|
|
int16_t mvc1 = block_context[1].mic.mbmi.mv[0].as_mv.col;
|
|
|
|
int16_t mvr2 = block_context[2].mic.mbmi.mv[0].as_mv.row;
|
|
|
|
int16_t mvc2 = block_context[2].mic.mbmi.mv[0].as_mv.col;
|
|
|
|
int16_t mvr3 = block_context[3].mic.mbmi.mv[0].as_mv.row;
|
|
|
|
int16_t mvc3 = block_context[3].mic.mbmi.mv[0].as_mv.col;
|
|
|
|
|
|
|
|
// Adjust sign if ref is alt_ref.
|
|
|
|
if (cm->ref_frame_sign_bias[ref0]) {
|
|
|
|
mvr0 *= -1;
|
|
|
|
mvc0 *= -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cm->ref_frame_sign_bias[ref1]) {
|
|
|
|
mvr1 *= -1;
|
|
|
|
mvc1 *= -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cm->ref_frame_sign_bias[ref2]) {
|
|
|
|
mvr2 *= -1;
|
|
|
|
mvc2 *= -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cm->ref_frame_sign_bias[ref3]) {
|
|
|
|
mvr3 *= -1;
|
|
|
|
mvc3 *= -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate mv distances.
|
|
|
|
d01 = MAX(abs(mvr0 - mvr1), abs(mvc0 - mvc1));
|
|
|
|
d23 = MAX(abs(mvr2 - mvr3), abs(mvc2 - mvc3));
|
|
|
|
d02 = MAX(abs(mvr0 - mvr2), abs(mvc0 - mvc2));
|
|
|
|
d13 = MAX(abs(mvr1 - mvr3), abs(mvc1 - mvc3));
|
|
|
|
|
|
|
|
if (d01 < FAST_MOTION_MV_THRESH && d23 < FAST_MOTION_MV_THRESH &&
|
|
|
|
d02 < FAST_MOTION_MV_THRESH && d13 < FAST_MOTION_MV_THRESH) {
|
|
|
|
// Set fast motion search level.
|
|
|
|
x->fast_ms = 1;
|
|
|
|
|
|
|
|
if (ref0 == ref1 && ref1 == ref2 && ref2 == ref3 &&
|
|
|
|
d01 < 2 && d23 < 2 && d02 < 2 && d13 < 2) {
|
|
|
|
// Set fast motion search level.
|
|
|
|
x->fast_ms = 2;
|
|
|
|
|
|
|
|
if (!d01 && !d23 && !d02 && !d13) {
|
|
|
|
x->fast_ms = 3;
|
|
|
|
x->subblock_ref = ref0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-12 19:06:47 +02:00
|
|
|
static INLINE void store_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
|
|
|
|
vpx_memcpy(ctx->pred_mv, x->pred_mv, sizeof(x->pred_mv));
|
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE void load_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
|
|
|
|
vpx_memcpy(x->pred_mv, ctx->pred_mv, sizeof(x->pred_mv));
|
|
|
|
}
|
|
|
|
|
2013-05-08 23:24:43 +02:00
|
|
|
// TODO(jingning,jimbankoski,rbultje): properly skip partition types that are
|
2013-08-01 18:04:15 +02:00
|
|
|
// unlikely to be selected depending on previous rate-distortion optimization
|
2013-05-08 23:24:43 +02:00
|
|
|
// results, for encoding speed-up.
|
2013-10-25 17:18:04 +02:00
|
|
|
static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
TOKENEXTRA **tp, int mi_row,
|
2013-08-27 20:05:08 +02:00
|
|
|
int mi_col, BLOCK_SIZE bsize, int *rate,
|
2013-07-17 18:56:46 +02:00
|
|
|
int64_t *dist, int do_recon, int64_t best_rd) {
|
2013-11-12 00:58:57 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
2013-08-28 21:22:37 +02:00
|
|
|
const int ms = num_8x8_blocks_wide_lookup[bsize] / 2;
|
2013-06-19 23:26:49 +02:00
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
|
2013-05-08 23:24:43 +02:00
|
|
|
PARTITION_CONTEXT sl[8], sa[8];
|
|
|
|
TOKENEXTRA *tp_orig = *tp;
|
2013-05-31 00:13:08 +02:00
|
|
|
int i, pl;
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE subsize;
|
2013-08-01 23:57:46 +02:00
|
|
|
int this_rate, sum_rate = 0, best_rate = INT_MAX;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
int64_t this_dist, sum_dist = 0, best_dist = INT64_MAX;
|
2013-08-01 23:57:46 +02:00
|
|
|
int64_t sum_rd = 0;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
int do_split = bsize >= BLOCK_8X8;
|
|
|
|
int do_rect = 1;
|
|
|
|
// Override skipping rectangular partition operations for edge blocks
|
2013-08-28 21:22:37 +02:00
|
|
|
const int force_horz_split = (mi_row + ms >= cm->mi_rows);
|
|
|
|
const int force_vert_split = (mi_col + ms >= cm->mi_cols);
|
2013-12-02 21:54:21 +01:00
|
|
|
const int xss = x->e_mbd.plane[1].subsampling_x;
|
|
|
|
const int yss = x->e_mbd.plane[1].subsampling_y;
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
int partition_none_allowed = !force_horz_split && !force_vert_split;
|
2013-12-02 21:54:21 +01:00
|
|
|
int partition_horz_allowed = !force_vert_split && yss <= xss &&
|
|
|
|
bsize >= BLOCK_8X8;
|
|
|
|
int partition_vert_allowed = !force_horz_split && xss <= yss &&
|
|
|
|
bsize >= BLOCK_8X8;
|
2013-08-13 21:34:32 +02:00
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
int partition_split_done = 0;
|
2013-07-10 23:27:20 +02:00
|
|
|
(void) *tp_orig;
|
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize < BLOCK_8X8) {
|
2013-08-01 18:04:15 +02:00
|
|
|
// When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
|
|
|
|
// there is nothing to be done.
|
2013-11-12 00:58:57 +01:00
|
|
|
if (x->ab_index != 0) {
|
2013-05-11 02:06:37 +02:00
|
|
|
*rate = 0;
|
|
|
|
*dist = 0;
|
|
|
|
return;
|
|
|
|
}
|
2013-08-01 18:04:15 +02:00
|
|
|
}
|
2013-11-06 22:34:23 +01:00
|
|
|
assert(num_8x8_blocks_wide_lookup[bsize] ==
|
|
|
|
num_8x8_blocks_high_lookup[bsize]);
|
2013-05-08 23:24:43 +02:00
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
if (bsize == BLOCK_16X16) {
|
2013-10-25 17:18:04 +02:00
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, bsize);
|
2013-10-07 20:20:10 +02:00
|
|
|
x->mb_energy = vp9_block_energy(cpi, x, bsize);
|
|
|
|
}
|
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// Determine partition types in search according to the speed features.
|
|
|
|
// The threshold set here has to be of square block size.
|
|
|
|
if (cpi->sf.auto_min_max_partition_size) {
|
|
|
|
partition_none_allowed &= (bsize <= cpi->sf.max_partition_size &&
|
|
|
|
bsize >= cpi->sf.min_partition_size);
|
|
|
|
partition_horz_allowed &= ((bsize <= cpi->sf.max_partition_size &&
|
|
|
|
bsize > cpi->sf.min_partition_size) ||
|
|
|
|
force_horz_split);
|
|
|
|
partition_vert_allowed &= ((bsize <= cpi->sf.max_partition_size &&
|
|
|
|
bsize > cpi->sf.min_partition_size) ||
|
|
|
|
force_vert_split);
|
|
|
|
do_split &= bsize > cpi->sf.min_partition_size;
|
|
|
|
}
|
|
|
|
if (cpi->sf.use_square_partition_only) {
|
|
|
|
partition_horz_allowed &= force_horz_split;
|
|
|
|
partition_vert_allowed &= force_vert_split;
|
|
|
|
}
|
|
|
|
|
2013-05-31 00:13:08 +02:00
|
|
|
save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-05-08 23:24:43 +02:00
|
|
|
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
if (cpi->sf.disable_split_var_thresh && partition_none_allowed) {
|
|
|
|
unsigned int source_variancey;
|
|
|
|
vp9_setup_src_planes(x, cpi->Source, mi_row, mi_col);
|
|
|
|
source_variancey = get_sby_perpixel_variance(cpi, x, bsize);
|
Fixes on feature disabling split based on variance
Adds a couple of minor fixes, which may be absorbed in Jingning's
patch. Thanks to Guillaume for pointing these out.
Also adjusts the thresholds for speed 1 and 2 to 16 and 32
respectively, to keep quality drops small.
Results:
--------
derfraw300: threshold = 16, psnr -0.082%, speedup 2-3%
threshold = 32, psnr -0.218%, speedup 5-6%
stdhdraw250: threshold = 16, psnr -0.031%, speedup 2-3%
threshold = 32, psnr -0.273%, speedup 5-6%
Change-Id: I4b11ae8296cca6c2a9f644be7e40de7c423b8330
2013-08-22 01:19:35 +02:00
|
|
|
if (source_variancey < cpi->sf.disable_split_var_thresh) {
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
do_split = 0;
|
Fixes on feature disabling split based on variance
Adds a couple of minor fixes, which may be absorbed in Jingning's
patch. Thanks to Guillaume for pointing these out.
Also adjusts the thresholds for speed 1 and 2 to 16 and 32
respectively, to keep quality drops small.
Results:
--------
derfraw300: threshold = 16, psnr -0.082%, speedup 2-3%
threshold = 32, psnr -0.218%, speedup 5-6%
stdhdraw250: threshold = 16, psnr -0.031%, speedup 2-3%
threshold = 32, psnr -0.273%, speedup 5-6%
Change-Id: I4b11ae8296cca6c2a9f644be7e40de7c423b8330
2013-08-22 01:19:35 +02:00
|
|
|
if (source_variancey < cpi->sf.disable_split_var_thresh / 2)
|
|
|
|
do_rect = 0;
|
|
|
|
}
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
}
|
2013-05-01 01:13:20 +02:00
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// PARTITION_NONE
|
|
|
|
if (partition_none_allowed) {
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &this_rate, &this_dist, bsize,
|
|
|
|
get_block_context(x, bsize), best_rd);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
if (this_rate != INT_MAX) {
|
|
|
|
if (bsize >= BLOCK_8X8) {
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context,
|
|
|
|
cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, bsize);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
this_rate += x->partition_cost[pl][PARTITION_NONE];
|
|
|
|
}
|
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_dist);
|
|
|
|
if (sum_rd < best_rd) {
|
2013-12-05 22:41:18 +01:00
|
|
|
int64_t stop_thresh = 4096;
|
|
|
|
int64_t stop_thresh_rd;
|
2013-09-07 01:59:55 +02:00
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
best_rate = this_rate;
|
|
|
|
best_dist = this_dist;
|
|
|
|
best_rd = sum_rd;
|
|
|
|
if (bsize >= BLOCK_8X8)
|
|
|
|
*(get_sb_partitioning(x, bsize)) = bsize;
|
2013-09-07 01:59:55 +02:00
|
|
|
|
|
|
|
// Adjust threshold according to partition size.
|
|
|
|
stop_thresh >>= 8 - (b_width_log2_lookup[bsize] +
|
|
|
|
b_height_log2_lookup[bsize]);
|
|
|
|
|
2013-12-05 22:41:18 +01:00
|
|
|
stop_thresh_rd = RDCOST(x->rdmult, x->rddiv, 0, stop_thresh);
|
2013-09-07 01:59:55 +02:00
|
|
|
// If obtained distortion is very small, choose current partition
|
|
|
|
// and stop splitting.
|
2013-12-05 22:41:18 +01:00
|
|
|
if (!x->e_mbd.lossless && best_rd < stop_thresh_rd) {
|
2013-09-07 01:59:55 +02:00
|
|
|
do_split = 0;
|
|
|
|
do_rect = 0;
|
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-09-12 19:06:47 +02:00
|
|
|
// store estimated motion vector
|
|
|
|
if (cpi->sf.adaptive_motion_search)
|
|
|
|
store_pred_mv(x, get_block_context(x, bsize));
|
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// PARTITION_SPLIT
|
|
|
|
sum_rd = 0;
|
|
|
|
// TODO(jingning): use the motion vectors given by the above search as
|
|
|
|
// the starting point of motion search in the following partition type check.
|
|
|
|
if (do_split) {
|
|
|
|
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
|
|
|
for (i = 0; i < 4 && sum_rd < best_rd; ++i) {
|
2013-08-28 21:22:37 +02:00
|
|
|
const int x_idx = (i & 1) * ms;
|
|
|
|
const int y_idx = (i >> 1) * ms;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
|
2013-08-28 21:22:37 +02:00
|
|
|
if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols)
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
continue;
|
2013-08-13 21:34:32 +02:00
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = i;
|
2013-09-12 19:06:47 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search)
|
|
|
|
load_pred_mv(x, get_block_context(x, bsize));
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2014-01-24 21:26:57 +01:00
|
|
|
get_block_context(x, subsize)->pred_interp_filter =
|
2013-12-13 02:31:04 +01:00
|
|
|
get_block_context(x, bsize)->mic.mbmi.interp_filter;
|
2013-10-25 17:18:04 +02:00
|
|
|
rd_pick_partition(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx, subsize,
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
&this_rate, &this_dist, i != 3, best_rd - sum_rd);
|
|
|
|
|
|
|
|
if (this_rate == INT_MAX) {
|
|
|
|
sum_rd = INT64_MAX;
|
|
|
|
} else {
|
|
|
|
sum_rate += this_rate;
|
|
|
|
sum_dist += this_dist;
|
2013-08-01 23:57:46 +02:00
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
|
2013-07-17 18:56:46 +02:00
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
if (sum_rd < best_rd && i == 4) {
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context,
|
|
|
|
cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, bsize);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
sum_rate += x->partition_cost[pl][PARTITION_SPLIT];
|
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
|
|
|
|
if (sum_rd < best_rd) {
|
|
|
|
best_rate = sum_rate;
|
|
|
|
best_dist = sum_dist;
|
|
|
|
best_rd = sum_rd;
|
|
|
|
*(get_sb_partitioning(x, bsize)) = subsize;
|
|
|
|
}
|
2013-09-30 20:58:22 +02:00
|
|
|
} else {
|
|
|
|
// skip rectangular partition test when larger block size
|
|
|
|
// gives better rd cost
|
|
|
|
if (cpi->sf.less_rectangular_check)
|
|
|
|
do_rect &= !partition_none_allowed;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
|
|
|
partition_split_done = 1;
|
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-05-08 23:24:43 +02:00
|
|
|
}
|
2013-07-03 23:43:23 +02:00
|
|
|
|
|
|
|
x->fast_ms = 0;
|
|
|
|
x->subblock_ref = 0;
|
|
|
|
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
if (partition_split_done &&
|
|
|
|
cpi->sf.using_small_partition_info) {
|
2013-08-03 02:19:29 +02:00
|
|
|
compute_fast_motion_search_level(cpi, bsize);
|
2013-07-03 23:43:23 +02:00
|
|
|
}
|
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// PARTITION_HORZ
|
|
|
|
if (partition_horz_allowed && do_rect) {
|
|
|
|
subsize = get_subsize(bsize, PARTITION_HORZ);
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = 0;
|
2013-09-12 19:06:47 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search)
|
|
|
|
load_pred_mv(x, get_block_context(x, bsize));
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2014-01-24 21:26:57 +01:00
|
|
|
get_block_context(x, subsize)->pred_interp_filter =
|
2013-12-13 02:31:04 +01:00
|
|
|
get_block_context(x, bsize)->mic.mbmi.interp_filter;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize,
|
|
|
|
get_block_context(x, subsize), best_rd);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
|
|
|
|
|
2013-08-28 21:22:37 +02:00
|
|
|
if (sum_rd < best_rd && mi_row + ms < cm->mi_rows) {
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
update_state(cpi, get_block_context(x, subsize), subsize, 0);
|
|
|
|
encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
|
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = 1;
|
2013-09-12 19:06:47 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search)
|
|
|
|
load_pred_mv(x, get_block_context(x, bsize));
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2014-01-24 21:26:57 +01:00
|
|
|
get_block_context(x, subsize)->pred_interp_filter =
|
2013-12-13 02:31:04 +01:00
|
|
|
get_block_context(x, bsize)->mic.mbmi.interp_filter;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row + ms, mi_col, &this_rate,
|
|
|
|
&this_dist, subsize, get_block_context(x, subsize),
|
|
|
|
best_rd - sum_rd);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
if (this_rate == INT_MAX) {
|
|
|
|
sum_rd = INT64_MAX;
|
|
|
|
} else {
|
|
|
|
sum_rate += this_rate;
|
|
|
|
sum_dist += this_dist;
|
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
|
2013-06-20 18:24:04 +02:00
|
|
|
}
|
2013-04-17 18:25:06 +02:00
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
if (sum_rd < best_rd) {
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context,
|
|
|
|
cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, bsize);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
sum_rate += x->partition_cost[pl][PARTITION_HORZ];
|
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
|
|
|
|
if (sum_rd < best_rd) {
|
|
|
|
best_rd = sum_rd;
|
|
|
|
best_rate = sum_rate;
|
|
|
|
best_dist = sum_dist;
|
|
|
|
*(get_sb_partitioning(x, bsize)) = subsize;
|
2013-07-17 18:56:46 +02:00
|
|
|
}
|
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
|
|
|
}
|
2013-07-17 18:56:46 +02:00
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// PARTITION_VERT
|
|
|
|
if (partition_vert_allowed && do_rect) {
|
|
|
|
subsize = get_subsize(bsize, PARTITION_VERT);
|
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = 0;
|
2013-09-12 19:06:47 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search)
|
|
|
|
load_pred_mv(x, get_block_context(x, bsize));
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2014-01-24 21:26:57 +01:00
|
|
|
get_block_context(x, subsize)->pred_interp_filter =
|
2013-12-13 02:31:04 +01:00
|
|
|
get_block_context(x, bsize)->mic.mbmi.interp_filter;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize,
|
|
|
|
get_block_context(x, subsize), best_rd);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
|
2013-08-28 21:22:37 +02:00
|
|
|
if (sum_rd < best_rd && mi_col + ms < cm->mi_cols) {
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
update_state(cpi, get_block_context(x, subsize), subsize, 0);
|
|
|
|
encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
|
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
*get_sb_index(x, subsize) = 1;
|
2013-09-12 19:06:47 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search)
|
|
|
|
load_pred_mv(x, get_block_context(x, bsize));
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2014-01-24 21:26:57 +01:00
|
|
|
get_block_context(x, subsize)->pred_interp_filter =
|
2013-12-13 02:31:04 +01:00
|
|
|
get_block_context(x, bsize)->mic.mbmi.interp_filter;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col + ms, &this_rate,
|
|
|
|
&this_dist, subsize, get_block_context(x, subsize),
|
|
|
|
best_rd - sum_rd);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
if (this_rate == INT_MAX) {
|
|
|
|
sum_rd = INT64_MAX;
|
|
|
|
} else {
|
|
|
|
sum_rate += this_rate;
|
|
|
|
sum_dist += this_dist;
|
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
|
2013-06-27 21:07:07 +02:00
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
|
|
|
if (sum_rd < best_rd) {
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context,
|
|
|
|
cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, bsize);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
sum_rate += x->partition_cost[pl][PARTITION_VERT];
|
|
|
|
sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
|
|
|
|
if (sum_rd < best_rd) {
|
|
|
|
best_rate = sum_rate;
|
|
|
|
best_dist = sum_dist;
|
|
|
|
best_rd = sum_rd;
|
|
|
|
*(get_sb_partitioning(x, bsize)) = subsize;
|
2013-06-27 21:07:07 +02:00
|
|
|
}
|
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-05-08 23:24:43 +02:00
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
|
|
|
|
|
2013-08-01 23:57:46 +02:00
|
|
|
*rate = best_rate;
|
|
|
|
*dist = best_dist;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-11-22 18:21:53 +01:00
|
|
|
if (best_rate < INT_MAX && best_dist < INT64_MAX && do_recon) {
|
|
|
|
int output_enabled = (bsize == BLOCK_64X64);
|
|
|
|
|
|
|
|
// Check the projected output rate for this SB against it's target
|
|
|
|
// and and if necessary apply a Q delta using segmentation to get
|
|
|
|
// closer to the target.
|
|
|
|
if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
|
|
|
|
select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled, best_rate);
|
|
|
|
}
|
|
|
|
encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, bsize);
|
|
|
|
}
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize == BLOCK_64X64) {
|
2013-05-08 23:24:43 +02:00
|
|
|
assert(tp_orig < *tp);
|
2013-08-01 23:57:46 +02:00
|
|
|
assert(best_rate < INT_MAX);
|
|
|
|
assert(best_dist < INT_MAX);
|
2013-05-11 02:06:37 +02:00
|
|
|
} else {
|
2013-05-08 23:24:43 +02:00
|
|
|
assert(tp_orig == *tp);
|
2013-05-11 02:06:37 +02:00
|
|
|
}
|
2013-05-08 23:24:43 +02:00
|
|
|
}
|
2013-04-17 18:25:06 +02:00
|
|
|
|
2013-07-01 17:27:12 +02:00
|
|
|
// Examines 64x64 block and chooses a best reference frame
|
2013-10-25 17:18:04 +02:00
|
|
|
static void rd_pick_reference_frame(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
int mi_row, int mi_col) {
|
2013-07-01 17:27:12 +02:00
|
|
|
VP9_COMMON * const cm = &cpi->common;
|
|
|
|
MACROBLOCK * const x = &cpi->mb;
|
2013-08-06 00:23:49 +02:00
|
|
|
int bsl = b_width_log2(BLOCK_64X64), bs = 1 << bsl;
|
2013-07-01 17:27:12 +02:00
|
|
|
int ms = bs / 2;
|
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
|
|
|
|
PARTITION_CONTEXT sl[8], sa[8];
|
|
|
|
int pl;
|
|
|
|
int r;
|
|
|
|
int64_t d;
|
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
save_context(cpi, mi_row, mi_col, a, l, sa, sl, BLOCK_64X64);
|
2013-07-01 17:27:12 +02:00
|
|
|
|
|
|
|
// Default is non mask (all reference frames allowed.
|
|
|
|
cpi->ref_frame_mask = 0;
|
|
|
|
|
|
|
|
// Do RD search for 64x64.
|
|
|
|
if ((mi_row + (ms >> 1) < cm->mi_rows) &&
|
|
|
|
(mi_col + (ms >> 1) < cm->mi_cols)) {
|
|
|
|
cpi->set_ref_frame_mask = 1;
|
2014-01-17 00:59:40 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &r, &d, BLOCK_64X64,
|
|
|
|
get_block_context(x, BLOCK_64X64), INT64_MAX);
|
2013-10-24 18:10:59 +02:00
|
|
|
pl = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
|
2013-10-24 16:31:07 +02:00
|
|
|
mi_row, mi_col, BLOCK_64X64);
|
2013-07-01 17:27:12 +02:00
|
|
|
r += x->partition_cost[pl][PARTITION_NONE];
|
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
*(get_sb_partitioning(x, BLOCK_64X64)) = BLOCK_64X64;
|
2013-07-01 17:27:12 +02:00
|
|
|
cpi->set_ref_frame_mask = 0;
|
|
|
|
}
|
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, BLOCK_64X64);
|
2013-07-01 17:27:12 +02:00
|
|
|
}
|
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
static void encode_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
|
2013-10-23 16:10:59 +02:00
|
|
|
int mi_row, TOKENEXTRA **tp) {
|
2014-01-08 23:51:00 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2013-05-08 23:24:43 +02:00
|
|
|
int mi_col;
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-05-08 23:24:43 +02:00
|
|
|
// Initialize the left context for the new SB row
|
2013-10-24 18:10:59 +02:00
|
|
|
vpx_memset(&cpi->left_context, 0, sizeof(cpi->left_context));
|
2013-10-24 18:10:59 +02:00
|
|
|
vpx_memset(cpi->left_seg_context, 0, sizeof(cpi->left_seg_context));
|
2013-05-08 23:24:43 +02:00
|
|
|
|
|
|
|
// Code each SB in the row
|
2013-10-25 17:18:04 +02:00
|
|
|
for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
|
2013-07-03 19:54:50 +02:00
|
|
|
mi_col += MI_BLOCK_SIZE) {
|
2013-06-21 21:54:52 +02:00
|
|
|
int dummy_rate;
|
|
|
|
int64_t dummy_dist;
|
2013-07-01 17:27:12 +02:00
|
|
|
|
2013-12-13 02:31:04 +01:00
|
|
|
BLOCK_SIZE i;
|
|
|
|
MACROBLOCK *x = &cpi->mb;
|
|
|
|
for (i = BLOCK_4X4; i < BLOCK_8X8; ++i) {
|
|
|
|
const int num_4x4_w = num_4x4_blocks_wide_lookup[i];
|
|
|
|
const int num_4x4_h = num_4x4_blocks_high_lookup[i];
|
|
|
|
const int num_4x4_blk = MAX(4, num_4x4_w * num_4x4_h);
|
|
|
|
for (x->sb_index = 0; x->sb_index < 4; ++x->sb_index)
|
|
|
|
for (x->mb_index = 0; x->mb_index < 4; ++x->mb_index)
|
|
|
|
for (x->b_index = 0; x->b_index < 16 / num_4x4_blk; ++x->b_index)
|
2014-01-24 21:26:57 +01:00
|
|
|
get_block_context(x, i)->pred_interp_filter = SWITCHABLE;
|
2013-12-13 02:31:04 +01:00
|
|
|
}
|
|
|
|
|
2013-09-27 02:43:55 +02:00
|
|
|
vp9_zero(cpi->mb.pred_mv);
|
2013-09-16 21:44:50 +02:00
|
|
|
|
2013-09-19 19:20:18 +02:00
|
|
|
if (cpi->sf.use_lastframe_partitioning ||
|
2013-06-20 16:46:51 +02:00
|
|
|
cpi->sf.use_one_partition_size_always ) {
|
2013-05-31 00:13:08 +02:00
|
|
|
const int idx_str = cm->mode_info_stride * mi_row + mi_col;
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str;
|
|
|
|
MODE_INFO **prev_mi_8x8 = cm->prev_mi_grid_visible + idx_str;
|
2013-06-20 18:32:19 +02:00
|
|
|
|
2013-07-31 18:33:58 +02:00
|
|
|
cpi->mb.source_variance = UINT_MAX;
|
2013-06-20 16:46:51 +02:00
|
|
|
if (cpi->sf.use_one_partition_size_always) {
|
2013-10-25 17:18:04 +02:00
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
|
|
|
|
set_partitioning(cpi, tile, mi_8x8, mi_row, mi_col);
|
|
|
|
rd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
|
2013-07-08 23:38:40 +02:00
|
|
|
&dummy_rate, &dummy_dist, 1);
|
2013-06-20 16:17:01 +02:00
|
|
|
} else {
|
2014-01-08 23:51:00 +01:00
|
|
|
if ((cm->current_video_frame
|
2013-07-02 03:18:50 +02:00
|
|
|
% cpi->sf.last_partitioning_redo_frequency) == 0
|
|
|
|
|| cm->prev_mi == 0
|
2014-01-08 23:51:00 +01:00
|
|
|
|| cm->show_frame == 0
|
|
|
|
|| cm->frame_type == KEY_FRAME
|
2013-12-13 18:32:05 +01:00
|
|
|
|| cpi->rc.is_src_frame_alt_ref
|
2013-10-01 17:57:18 +02:00
|
|
|
|| ((cpi->sf.use_lastframe_partitioning ==
|
|
|
|
LAST_FRAME_PARTITION_LOW_MOTION) &&
|
2014-01-08 23:51:00 +01:00
|
|
|
sb_has_motion(cm, prev_mi_8x8))) {
|
2013-07-24 15:07:37 +02:00
|
|
|
// If required set upper and lower partition size limits
|
|
|
|
if (cpi->sf.auto_min_max_partition_size) {
|
2013-10-25 17:18:04 +02:00
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
|
|
|
|
rd_auto_partition_range(cpi, tile, mi_row, mi_col,
|
2013-07-24 15:07:37 +02:00
|
|
|
&cpi->sf.min_partition_size,
|
|
|
|
&cpi->sf.max_partition_size);
|
|
|
|
}
|
2013-10-25 17:18:04 +02:00
|
|
|
rd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64,
|
2013-07-17 18:56:46 +02:00
|
|
|
&dummy_rate, &dummy_dist, 1, INT64_MAX);
|
2013-06-20 16:17:01 +02:00
|
|
|
} else {
|
2014-01-08 23:51:00 +01:00
|
|
|
copy_partitioning(cm, mi_8x8, prev_mi_8x8);
|
2013-10-25 17:18:04 +02:00
|
|
|
rd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
|
2013-07-08 23:38:40 +02:00
|
|
|
&dummy_rate, &dummy_dist, 1);
|
2013-06-20 16:17:01 +02:00
|
|
|
}
|
2013-06-20 18:32:19 +02:00
|
|
|
}
|
2013-06-20 16:17:01 +02:00
|
|
|
} else {
|
2013-07-24 15:07:37 +02:00
|
|
|
// If required set upper and lower partition size limits
|
|
|
|
if (cpi->sf.auto_min_max_partition_size) {
|
2013-10-25 17:18:04 +02:00
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
|
|
|
|
rd_auto_partition_range(cpi, tile, mi_row, mi_col,
|
2013-09-04 00:46:22 +02:00
|
|
|
&cpi->sf.min_partition_size,
|
2013-07-24 15:07:37 +02:00
|
|
|
&cpi->sf.max_partition_size);
|
|
|
|
}
|
2013-10-25 17:18:04 +02:00
|
|
|
rd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64,
|
2013-07-17 18:56:46 +02:00
|
|
|
&dummy_rate, &dummy_dist, 1, INT64_MAX);
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2011-09-30 17:45:16 +02:00
|
|
|
}
|
|
|
|
|
2012-10-31 01:53:32 +01:00
|
|
|
static void init_encode_frame_mb_context(VP9_COMP *cpi) {
|
2013-07-08 23:54:04 +02:00
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
|
|
|
const int aligned_mi_cols = mi_cols_aligned_to_sb(cm->mi_cols);
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
x->act_zbin_adj = 0;
|
|
|
|
cpi->seg0_idx = 0;
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
xd->mode_info_stride = cm->mode_info_stride;
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Copy data over into macro block data structures.
|
2013-04-24 01:22:47 +02:00
|
|
|
vp9_setup_src_planes(x, cpi->Source, 0, 0);
|
2013-04-20 04:16:14 +02:00
|
|
|
|
|
|
|
// TODO(jkoleszar): are these initializations required?
|
2014-01-06 23:50:54 +01:00
|
|
|
setup_pre_planes(xd, 0, get_ref_frame_buffer(cpi, LAST_FRAME), 0, 0, NULL);
|
2013-10-24 21:20:35 +02:00
|
|
|
setup_dst_planes(xd, get_frame_new_buffer(cm), 0, 0);
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2013-07-02 02:28:08 +02:00
|
|
|
setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->mbmi.mode = DC_PRED;
|
|
|
|
xd->mi_8x8[0]->mbmi.uv_mode = DC_PRED;
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2013-12-19 03:52:58 +01:00
|
|
|
vp9_zero(cm->counts.y_mode);
|
|
|
|
vp9_zero(cm->counts.uv_mode);
|
2013-10-16 01:09:28 +02:00
|
|
|
vp9_zero(cm->counts.inter_mode);
|
2013-11-22 23:26:39 +01:00
|
|
|
vp9_zero(cm->counts.partition);
|
2013-12-19 03:52:58 +01:00
|
|
|
vp9_zero(cm->counts.intra_inter);
|
2013-12-17 05:12:47 +01:00
|
|
|
vp9_zero(cm->counts.comp_inter);
|
|
|
|
vp9_zero(cm->counts.single_ref);
|
|
|
|
vp9_zero(cm->counts.comp_ref);
|
2013-07-24 02:02:08 +02:00
|
|
|
vp9_zero(cm->counts.tx);
|
2014-01-29 23:48:42 +01:00
|
|
|
vp9_zero(cm->counts.skip);
|
2013-04-16 09:18:02 +02:00
|
|
|
|
2013-04-29 19:37:25 +02:00
|
|
|
// Note: this memset assumes above_context[0], [1] and [2]
|
|
|
|
// are allocated as part of the same buffer.
|
2013-10-24 18:10:59 +02:00
|
|
|
vpx_memset(cpi->above_context[0], 0,
|
|
|
|
sizeof(*cpi->above_context[0]) *
|
|
|
|
2 * aligned_mi_cols * MAX_MB_PLANE);
|
2013-10-24 18:10:59 +02:00
|
|
|
vpx_memset(cpi->above_seg_context, 0,
|
|
|
|
sizeof(*cpi->above_seg_context) * aligned_mi_cols);
|
2011-06-08 17:00:59 +02:00
|
|
|
}
|
2013-02-20 16:27:35 +01:00
|
|
|
|
2013-02-13 23:22:15 +01:00
|
|
|
static void switch_lossless_mode(VP9_COMP *cpi, int lossless) {
|
|
|
|
if (lossless) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
// printf("Switching to lossless\n");
|
2013-10-23 23:28:39 +02:00
|
|
|
cpi->mb.fwd_txm4x4 = vp9_fwht4x4;
|
2013-10-08 20:27:56 +02:00
|
|
|
cpi->mb.e_mbd.itxm_add = vp9_iwht4x4_add;
|
2013-06-19 23:26:49 +02:00
|
|
|
cpi->mb.optimize = 0;
|
2013-08-09 23:41:51 +02:00
|
|
|
cpi->common.lf.filter_level = 0;
|
2013-06-19 23:26:49 +02:00
|
|
|
cpi->zbin_mode_boost_enabled = 0;
|
2013-07-19 20:37:13 +02:00
|
|
|
cpi->common.tx_mode = ONLY_4X4;
|
2013-02-13 23:22:15 +01:00
|
|
|
} else {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
// printf("Not lossless\n");
|
2013-10-23 23:28:39 +02:00
|
|
|
cpi->mb.fwd_txm4x4 = vp9_fdct4x4;
|
2013-10-08 20:27:56 +02:00
|
|
|
cpi->mb.e_mbd.itxm_add = vp9_idct4x4_add;
|
2013-02-13 23:22:15 +01:00
|
|
|
}
|
|
|
|
}
|
2013-02-20 16:27:35 +01:00
|
|
|
|
2013-07-19 20:37:13 +02:00
|
|
|
static void switch_tx_mode(VP9_COMP *cpi) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
if (cpi->sf.tx_size_search_method == USE_LARGESTALL &&
|
2013-07-19 20:37:13 +02:00
|
|
|
cpi->common.tx_mode >= ALLOW_32X32)
|
|
|
|
cpi->common.tx_mode = ALLOW_32X32;
|
2013-06-25 01:43:26 +02:00
|
|
|
}
|
|
|
|
|
2012-10-31 01:53:32 +01:00
|
|
|
static void encode_frame_internal(VP9_COMP *cpi) {
|
2013-04-26 20:57:17 +02:00
|
|
|
int mi_row;
|
2014-01-08 23:51:00 +01:00
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-04-15 18:31:27 +02:00
|
|
|
// fprintf(stderr, "encode_frame_internal frame %d (%d) type %d\n",
|
|
|
|
// cpi->common.current_video_frame, cpi->common.show_frame,
|
|
|
|
// cm->frame_type);
|
2012-09-10 07:42:35 +02:00
|
|
|
|
2011-09-30 17:45:16 +02:00
|
|
|
// debug output
|
2011-10-07 17:58:28 +02:00
|
|
|
#if DBG_PRNT_SEGMAP
|
2012-07-14 00:21:29 +02:00
|
|
|
{
|
|
|
|
FILE *statsfile;
|
|
|
|
statsfile = fopen("segmap2.stt", "a");
|
|
|
|
fprintf(statsfile, "\n");
|
|
|
|
fclose(statsfile);
|
|
|
|
}
|
2011-09-30 17:45:16 +02:00
|
|
|
#endif
|
|
|
|
|
2013-07-24 02:02:08 +02:00
|
|
|
vp9_zero(cm->counts.switchable_interp);
|
2013-09-25 02:24:35 +02:00
|
|
|
vp9_zero(cpi->tx_stepdown_count);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
xd->mi_8x8 = cm->mi_grid_visible;
|
|
|
|
// required for vp9_frame_init_quantizer
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0] = cm->mi;
|
2013-09-11 19:45:44 +02:00
|
|
|
|
|
|
|
xd->last_mi = cm->prev_mi;
|
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
vp9_zero(cm->counts.mv);
|
2013-05-31 18:18:59 +02:00
|
|
|
vp9_zero(cpi->coef_counts);
|
2013-07-24 02:02:08 +02:00
|
|
|
vp9_zero(cm->counts.eob_branch);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
cpi->mb.e_mbd.lossless = cm->base_qindex == 0 && cm->y_dc_delta_q == 0
|
|
|
|
&& cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0;
|
2013-02-13 23:22:15 +01:00
|
|
|
switch_lossless_mode(cpi, cpi->mb.e_mbd.lossless);
|
2013-02-20 16:27:35 +01:00
|
|
|
|
2012-10-30 22:25:33 +01:00
|
|
|
vp9_frame_init_quantizer(cpi);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
vp9_initialize_rd_consts(cpi);
|
2012-10-30 22:25:33 +01:00
|
|
|
vp9_initialize_me_consts(cpi, cm->base_qindex);
|
2013-07-19 20:37:13 +02:00
|
|
|
switch_tx_mode(cpi);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
|
|
|
|
// Initialize encode frame context.
|
2011-06-08 17:00:59 +02:00
|
|
|
init_encode_frame_mb_context(cpi);
|
2012-02-10 01:11:00 +01:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Build a frame level activity map
|
|
|
|
build_activity_map(cpi);
|
|
|
|
}
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2013-08-20 21:55:41 +02:00
|
|
|
// Re-initialize encode frame context.
|
2012-07-14 00:21:29 +02:00
|
|
|
init_encode_frame_mb_context(cpi);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-07-03 02:19:16 +02:00
|
|
|
vp9_zero(cpi->rd_comp_pred_diff);
|
2013-07-08 23:49:33 +02:00
|
|
|
vp9_zero(cpi->rd_filter_diff);
|
2013-07-03 02:19:16 +02:00
|
|
|
vp9_zero(cpi->rd_tx_select_diff);
|
|
|
|
vp9_zero(cpi->rd_tx_select_threshes);
|
2013-05-24 20:11:06 +02:00
|
|
|
|
2013-05-29 22:42:23 +02:00
|
|
|
set_prev_mi(cm);
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
{
|
2013-06-19 23:26:49 +02:00
|
|
|
struct vpx_usec_timer emr_timer;
|
2012-07-14 00:21:29 +02:00
|
|
|
vpx_usec_timer_start(&emr_timer);
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
{
|
[WIP] Add column-based tiling.
This patch adds column-based tiling. The idea is to make each tile
independently decodable (after reading the common frame header) and
also independendly encodable (minus within-frame cost adjustments in
the RD loop) to speed-up hardware & software en/decoders if they used
multi-threading. Column-based tiling has the added advantage (over
other tiling methods) that it minimizes realtime use-case latency,
since all threads can start encoding data as soon as the first SB-row
worth of data is available to the encoder.
There is some test code that does random tile ordering in the decoder,
to confirm that each tile is indeed independently decodable from other
tiles in the same frame. At tile edges, all contexts assume default
values (i.e. 0, 0 motion vector, no coefficients, DC intra4x4 mode),
and motion vector search and ordering do not cross tiles in the same
frame.
t log
Tile independence is not maintained between frames ATM, i.e. tile 0 of
frame 1 is free to use motion vectors that point into any tile of frame
0. We support 1 (i.e. no tiling), 2 or 4 column-tiles.
The loopfilter crosses tile boundaries. I discussed this briefly with Aki
and he says that's OK. An in-loop loopfilter would need to do some sync
between tile threads, but that shouldn't be a big issue.
Resuls: with tiling disabled, we go up slightly because of improved edge
use in the intra4x4 prediction. With 2 tiles, we lose about ~1% on derf,
~0.35% on HD and ~0.55% on STD/HD. With 4 tiles, we lose another ~1.5%
on derf ~0.77% on HD and ~0.85% on STD/HD. Most of this loss is
concentrated in the low-bitrate end of clips, and most of it is because
of the loss of edges at tile boundaries and the resulting loss of intra
predictors.
TODO:
- more tiles (perhaps allow row-based tiling also, and max. 8 tiles)?
- maybe optionally (for EC purposes), motion vectors themselves
should not cross tile edges, or we should emulate such borders as
if they were off-frame, to limit error propagation to within one
tile only. This doesn't have to be the default behaviour but could
be an optional bitstream flag.
Change-Id: I5951c3a0742a767b20bc9fb5af685d9892c2c96f
2013-02-01 18:35:28 +01:00
|
|
|
// Take tiles into account and give start/end MB
|
2013-02-20 19:16:24 +01:00
|
|
|
int tile_col, tile_row;
|
2013-02-08 20:33:11 +01:00
|
|
|
TOKENEXTRA *tp = cpi->tok;
|
2013-07-16 23:47:15 +02:00
|
|
|
const int tile_cols = 1 << cm->log2_tile_cols;
|
|
|
|
const int tile_rows = 1 << cm->log2_tile_rows;
|
2013-02-28 02:09:12 +01:00
|
|
|
|
2013-07-16 23:47:15 +02:00
|
|
|
for (tile_row = 0; tile_row < tile_rows; tile_row++) {
|
|
|
|
for (tile_col = 0; tile_col < tile_cols; tile_col++) {
|
2013-10-25 17:18:04 +02:00
|
|
|
TileInfo tile;
|
2013-02-20 19:16:24 +01:00
|
|
|
TOKENEXTRA *tp_old = tp;
|
|
|
|
|
|
|
|
// For each row of SBs in the frame
|
2013-10-25 17:18:04 +02:00
|
|
|
vp9_tile_init(&tile, cm, tile_row, tile_col);
|
|
|
|
for (mi_row = tile.mi_row_start;
|
|
|
|
mi_row < tile.mi_row_end; mi_row += 8)
|
2013-10-23 16:10:59 +02:00
|
|
|
encode_sb_row(cpi, &tile, mi_row, &tp);
|
2013-06-19 23:26:49 +02:00
|
|
|
|
2013-06-12 19:30:06 +02:00
|
|
|
cpi->tok_count[tile_row][tile_col] = (unsigned int)(tp - tp_old);
|
2013-07-16 23:47:15 +02:00
|
|
|
assert(tp - cpi->tok <= get_token_alloc(cm->mb_rows, cm->mb_cols));
|
[WIP] Add column-based tiling.
This patch adds column-based tiling. The idea is to make each tile
independently decodable (after reading the common frame header) and
also independendly encodable (minus within-frame cost adjustments in
the RD loop) to speed-up hardware & software en/decoders if they used
multi-threading. Column-based tiling has the added advantage (over
other tiling methods) that it minimizes realtime use-case latency,
since all threads can start encoding data as soon as the first SB-row
worth of data is available to the encoder.
There is some test code that does random tile ordering in the decoder,
to confirm that each tile is indeed independently decodable from other
tiles in the same frame. At tile edges, all contexts assume default
values (i.e. 0, 0 motion vector, no coefficients, DC intra4x4 mode),
and motion vector search and ordering do not cross tiles in the same
frame.
t log
Tile independence is not maintained between frames ATM, i.e. tile 0 of
frame 1 is free to use motion vectors that point into any tile of frame
0. We support 1 (i.e. no tiling), 2 or 4 column-tiles.
The loopfilter crosses tile boundaries. I discussed this briefly with Aki
and he says that's OK. An in-loop loopfilter would need to do some sync
between tile threads, but that shouldn't be a big issue.
Resuls: with tiling disabled, we go up slightly because of improved edge
use in the intra4x4 prediction. With 2 tiles, we lose about ~1% on derf,
~0.35% on HD and ~0.55% on STD/HD. With 4 tiles, we lose another ~1.5%
on derf ~0.77% on HD and ~0.85% on STD/HD. Most of this loss is
concentrated in the low-bitrate end of clips, and most of it is because
of the loss of edges at tile boundaries and the resulting loss of intra
predictors.
TODO:
- more tiles (perhaps allow row-based tiling also, and max. 8 tiles)?
- maybe optionally (for EC purposes), motion vectors themselves
should not cross tile edges, or we should emulate such borders as
if they were off-frame, to limit error propagation to within one
tile only. This doesn't have to be the default behaviour but could
be an optional bitstream flag.
Change-Id: I5951c3a0742a767b20bc9fb5af685d9892c2c96f
2013-02-01 18:35:28 +01:00
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
vpx_usec_timer_mark(&emr_timer);
|
2013-07-30 19:16:03 +02:00
|
|
|
cpi->time_encode_sb_row += vpx_usec_timer_elapsed(&emr_timer);
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
|
|
|
|
2013-07-09 01:48:47 +02:00
|
|
|
if (cpi->sf.skip_encode_sb) {
|
|
|
|
int j;
|
|
|
|
unsigned int intra_count = 0, inter_count = 0;
|
|
|
|
for (j = 0; j < INTRA_INTER_CONTEXTS; ++j) {
|
2013-12-19 03:52:58 +01:00
|
|
|
intra_count += cm->counts.intra_inter[j][0];
|
|
|
|
inter_count += cm->counts.intra_inter[j][1];
|
2013-07-09 01:48:47 +02:00
|
|
|
}
|
|
|
|
cpi->sf.skip_encode_frame = ((intra_count << 2) < inter_count);
|
|
|
|
cpi->sf.skip_encode_frame &= (cm->frame_type != KEY_FRAME);
|
|
|
|
cpi->sf.skip_encode_frame &= cm->show_frame;
|
|
|
|
} else {
|
|
|
|
cpi->sf.skip_encode_frame = 0;
|
|
|
|
}
|
|
|
|
|
2010-05-18 17:58:33 +02:00
|
|
|
#if 0
|
2012-07-14 00:21:29 +02:00
|
|
|
// Keep record of the total distortion this time around for future use
|
|
|
|
cpi->last_frame_distortion = cpi->frame_distortion;
|
2010-05-18 17:58:33 +02:00
|
|
|
#endif
|
|
|
|
}
|
Dual 16x16 inter prediction.
This patch introduces the concept of dual inter16x16 prediction. A
16x16 inter-predicted macroblock can use 2 references instead of 1,
where both references use the same mvmode (new, near/est, zero). In the
case of newmv, this means that two MVs are coded instead of one. The
frame can be encoded in 3 ways: all MBs single-prediction, all MBs dual
prediction, or per-MB single/dual prediction selection ("hybrid"), in
which case a single bit is coded per-MB to indicate whether the MB uses
single or dual inter prediction.
In the future, we can (maybe?) get further gains by mixing this with
Adrian's 32x32 work, per-segment dual prediction settings, or adding
support for dual splitmv/8x8mv inter prediction.
Gain (on derf-set, CQ mode) is ~2.8% (SSIM) or ~3.6% (glb PSNR). Most
gain is at medium/high bitrates, but there's minor gains at low bitrates
also. Output was confirmed to match between encoder and decoder.
Note for optimization people: this patch introduces a 2nd version of
16x16/8x8 sixtap/bilin functions, which does an avg instead of a
store. They may want to look and make sure this is implemented to
their satisfaction so we can optimize it best in the future.
Change-ID: I59dc84b07cbb3ccf073ac0f756d03d294cb19281
2011-12-06 20:53:02 +01:00
|
|
|
|
2012-10-31 01:53:32 +01:00
|
|
|
static int check_dual_ref_flags(VP9_COMP *cpi) {
|
2013-08-14 20:20:33 +02:00
|
|
|
const int ref_flags = cpi->ref_frame_flags;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-08-14 20:20:33 +02:00
|
|
|
if (vp9_segfeature_active(&cpi->common.seg, 1, SEG_LVL_REF_FRAME)) {
|
2012-07-14 00:21:29 +02:00
|
|
|
return 0;
|
|
|
|
} else {
|
2013-06-19 23:26:49 +02:00
|
|
|
return (!!(ref_flags & VP9_GOLD_FLAG) + !!(ref_flags & VP9_LAST_FLAG)
|
|
|
|
+ !!(ref_flags & VP9_ALT_FLAG)) >= 2;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2012-03-22 18:03:14 +01:00
|
|
|
}
|
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
static int get_skip_flag(MODE_INFO **mi_8x8, int mis, int ymbs, int xmbs) {
|
2013-01-06 03:20:25 +01:00
|
|
|
int x, y;
|
|
|
|
|
|
|
|
for (y = 0; y < ymbs; y++) {
|
|
|
|
for (x = 0; x < xmbs; x++) {
|
2013-09-11 19:45:44 +02:00
|
|
|
if (!mi_8x8[y * mis + x]->mbmi.skip_coeff)
|
2013-01-06 03:20:25 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
static void set_txfm_flag(MODE_INFO **mi_8x8, int mis, int ymbs, int xmbs,
|
2013-08-28 04:47:53 +02:00
|
|
|
TX_SIZE tx_size) {
|
2013-01-06 03:20:25 +01:00
|
|
|
int x, y;
|
|
|
|
|
|
|
|
for (y = 0; y < ymbs; y++) {
|
2013-02-28 22:18:02 +01:00
|
|
|
for (x = 0; x < xmbs; x++)
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_8x8[y * mis + x]->mbmi.tx_size = tx_size;
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
static void reset_skip_txfm_size_b(VP9_COMMON *cm, MODE_INFO **mi_8x8,
|
2013-09-11 19:45:44 +02:00
|
|
|
int mis, TX_SIZE max_tx_size, int bw, int bh,
|
2013-08-27 20:05:08 +02:00
|
|
|
int mi_row, int mi_col, BLOCK_SIZE bsize) {
|
2013-09-24 17:36:59 +02:00
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) {
|
2013-04-28 00:26:39 +02:00
|
|
|
return;
|
2013-09-24 17:36:59 +02:00
|
|
|
} else {
|
|
|
|
MB_MODE_INFO * const mbmi = &mi_8x8[0]->mbmi;
|
|
|
|
if (mbmi->tx_size > max_tx_size) {
|
|
|
|
const int ymbs = MIN(bh, cm->mi_rows - mi_row);
|
|
|
|
const int xmbs = MIN(bw, cm->mi_cols - mi_col);
|
|
|
|
|
|
|
|
assert(vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP) ||
|
|
|
|
get_skip_flag(mi_8x8, mis, ymbs, xmbs));
|
|
|
|
set_txfm_flag(mi_8x8, mis, ymbs, xmbs, max_tx_size);
|
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
static void reset_skip_txfm_size_sb(VP9_COMMON *cm, MODE_INFO **mi_8x8,
|
2013-08-26 23:22:54 +02:00
|
|
|
TX_SIZE max_tx_size, int mi_row, int mi_col,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize) {
|
2013-04-28 00:26:39 +02:00
|
|
|
const int mis = cm->mode_info_stride;
|
2013-08-26 23:22:54 +02:00
|
|
|
int bw, bh;
|
|
|
|
const int bs = num_8x8_blocks_wide_lookup[bsize], hbs = bs / 2;
|
2013-04-28 00:26:39 +02:00
|
|
|
|
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
|
|
|
|
return;
|
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
bw = num_8x8_blocks_wide_lookup[mi_8x8[0]->mbmi.sb_type];
|
|
|
|
bh = num_8x8_blocks_high_lookup[mi_8x8[0]->mbmi.sb_type];
|
2013-04-28 00:26:39 +02:00
|
|
|
|
2013-08-26 23:22:54 +02:00
|
|
|
if (bw == bs && bh == bs) {
|
2014-01-08 23:51:00 +01:00
|
|
|
reset_skip_txfm_size_b(cm, mi_8x8, mis, max_tx_size, bs, bs, mi_row,
|
2013-06-19 23:26:49 +02:00
|
|
|
mi_col, bsize);
|
2013-08-26 23:22:54 +02:00
|
|
|
} else if (bw == bs && bh < bs) {
|
2014-01-08 23:51:00 +01:00
|
|
|
reset_skip_txfm_size_b(cm, mi_8x8, mis, max_tx_size, bs, hbs, mi_row,
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_col, bsize);
|
2014-01-08 23:51:00 +01:00
|
|
|
reset_skip_txfm_size_b(cm, mi_8x8 + hbs * mis, mis, max_tx_size, bs, hbs,
|
2013-08-26 23:22:54 +02:00
|
|
|
mi_row + hbs, mi_col, bsize);
|
|
|
|
} else if (bw < bs && bh == bs) {
|
2014-01-08 23:51:00 +01:00
|
|
|
reset_skip_txfm_size_b(cm, mi_8x8, mis, max_tx_size, hbs, bs, mi_row,
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_col, bsize);
|
2014-01-08 23:51:00 +01:00
|
|
|
reset_skip_txfm_size_b(cm, mi_8x8 + hbs, mis, max_tx_size, hbs, bs, mi_row,
|
2013-08-26 23:22:54 +02:00
|
|
|
mi_col + hbs, bsize);
|
2013-09-11 19:45:44 +02:00
|
|
|
|
2013-04-28 00:26:39 +02:00
|
|
|
} else {
|
2013-08-27 20:05:08 +02:00
|
|
|
const BLOCK_SIZE subsize = subsize_lookup[PARTITION_SPLIT][bsize];
|
2013-04-28 00:26:39 +02:00
|
|
|
int n;
|
|
|
|
|
2013-08-26 23:22:54 +02:00
|
|
|
assert(bw < bs && bh < bs);
|
2013-04-28 00:26:39 +02:00
|
|
|
|
|
|
|
for (n = 0; n < 4; n++) {
|
2013-08-26 23:22:54 +02:00
|
|
|
const int mi_dc = hbs * (n & 1);
|
|
|
|
const int mi_dr = hbs * (n >> 1);
|
2013-04-28 00:26:39 +02:00
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
reset_skip_txfm_size_sb(cm, &mi_8x8[mi_dr * mis + mi_dc], max_tx_size,
|
2013-08-26 23:22:54 +02:00
|
|
|
mi_row + mi_dr, mi_col + mi_dc, subsize);
|
2013-04-28 00:26:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
static void reset_skip_txfm_size(VP9_COMMON *cm, TX_SIZE txfm_max) {
|
2013-04-26 20:57:17 +02:00
|
|
|
int mi_row, mi_col;
|
2013-01-06 03:20:25 +01:00
|
|
|
const int mis = cm->mode_info_stride;
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO **mi_8x8, **mi_ptr = cm->mi_grid_visible;
|
2012-10-12 03:19:20 +02:00
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
for (mi_row = 0; mi_row < cm->mi_rows; mi_row += 8, mi_ptr += 8 * mis) {
|
2013-09-11 19:45:44 +02:00
|
|
|
mi_8x8 = mi_ptr;
|
|
|
|
for (mi_col = 0; mi_col < cm->mi_cols; mi_col += 8, mi_8x8 += 8) {
|
2014-01-08 23:51:00 +01:00
|
|
|
reset_skip_txfm_size_sb(cm, mi_8x8, txfm_max, mi_row, mi_col,
|
2013-09-11 19:45:44 +02:00
|
|
|
BLOCK_64X64);
|
|
|
|
}
|
2012-10-12 03:19:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-31 20:08:27 +01:00
|
|
|
static MV_REFERENCE_FRAME get_frame_type(VP9_COMP *cpi) {
|
2013-10-03 18:07:24 +02:00
|
|
|
if (frame_is_intra_only(&cpi->common))
|
2014-01-31 20:08:27 +01:00
|
|
|
return INTRA_FRAME;
|
2013-12-13 18:32:05 +01:00
|
|
|
else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
|
2014-01-31 20:08:27 +01:00
|
|
|
return ALTREF_FRAME;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
|
2014-01-31 20:08:27 +01:00
|
|
|
return LAST_FRAME;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
else
|
2014-01-31 20:08:27 +01:00
|
|
|
return GOLDEN_FRAME;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
2013-07-19 20:37:13 +02:00
|
|
|
static void select_tx_mode(VP9_COMP *cpi) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
if (cpi->oxcf.lossless) {
|
2013-07-19 20:37:13 +02:00
|
|
|
cpi->common.tx_mode = ONLY_4X4;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else if (cpi->common.current_video_frame == 0) {
|
2013-07-19 20:37:13 +02:00
|
|
|
cpi->common.tx_mode = TX_MODE_SELECT;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else {
|
2013-07-03 23:47:54 +02:00
|
|
|
if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
|
2013-07-19 20:37:13 +02:00
|
|
|
cpi->common.tx_mode = ALLOW_32X32;
|
2013-07-03 23:47:54 +02:00
|
|
|
} else if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
int frame_type = get_frame_type(cpi);
|
2013-07-19 20:37:13 +02:00
|
|
|
cpi->common.tx_mode =
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32]
|
|
|
|
> cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
|
|
|
|
ALLOW_32X32 : TX_MODE_SELECT;
|
|
|
|
} else {
|
|
|
|
unsigned int total = 0;
|
|
|
|
int i;
|
2013-07-27 02:15:37 +02:00
|
|
|
for (i = 0; i < TX_SIZES; ++i)
|
2013-09-25 02:24:35 +02:00
|
|
|
total += cpi->tx_stepdown_count[i];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
if (total) {
|
2013-09-25 02:24:35 +02:00
|
|
|
double fraction = (double)cpi->tx_stepdown_count[0] / total;
|
2013-07-19 20:37:13 +02:00
|
|
|
cpi->common.tx_mode = fraction > 0.90 ? ALLOW_32X32 : TX_MODE_SELECT;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
// printf("fraction = %f\n", fraction);
|
|
|
|
} // else keep unchanged
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-01-29 17:39:39 +01:00
|
|
|
// Start RTC Exploration
|
|
|
|
typedef enum {
|
|
|
|
BOTH_ZERO = 0,
|
|
|
|
ZERO_PLUS_PREDICTED = 1,
|
|
|
|
BOTH_PREDICTED = 2,
|
|
|
|
NEW_PLUS_NON_INTRA = 3,
|
|
|
|
BOTH_NEW = 4,
|
|
|
|
INTRA_PLUS_NON_INTRA = 5,
|
|
|
|
BOTH_INTRA = 6,
|
|
|
|
INVALID_CASE = 9
|
|
|
|
} motion_vector_context;
|
|
|
|
|
|
|
|
static void set_mode_info(MB_MODE_INFO *mbmi, BLOCK_SIZE bsize,
|
|
|
|
MB_PREDICTION_MODE mode, int mi_row, int mi_col) {
|
|
|
|
mbmi->interp_filter = EIGHTTAP;
|
|
|
|
mbmi->mode = mode;
|
|
|
|
mbmi->mv[0].as_int = 0;
|
|
|
|
mbmi->mv[1].as_int = 0;
|
|
|
|
if (mode < NEARESTMV) {
|
|
|
|
mbmi->ref_frame[0] = INTRA_FRAME;
|
|
|
|
} else {
|
|
|
|
mbmi->ref_frame[0] = LAST_FRAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
mbmi->ref_frame[1] = INTRA_FRAME;
|
|
|
|
mbmi->tx_size = max_txsize_lookup[bsize];
|
|
|
|
mbmi->uv_mode = mode;
|
|
|
|
mbmi->skip_coeff = 0;
|
|
|
|
mbmi->sb_type = bsize;
|
|
|
|
mbmi->segment_id = 0;
|
|
|
|
}
|
2014-01-30 20:48:16 +01:00
|
|
|
static INLINE int get_block_row(int b32i, int b16i, int b8i) {
|
2014-01-29 17:39:39 +01:00
|
|
|
return ((b32i >> 1) << 2) + ((b16i >> 1) << 1) + (b8i >> 1);
|
|
|
|
}
|
2014-01-30 20:48:16 +01:00
|
|
|
static INLINE int get_block_col(int b32i, int b16i, int b8i) {
|
2014-01-29 17:39:39 +01:00
|
|
|
return ((b32i & 1) << 2) + ((b16i & 1) << 1) + (b8i & 1);
|
|
|
|
}
|
|
|
|
static void rtc_use_partition(VP9_COMP *cpi,
|
|
|
|
const TileInfo *const tile,
|
|
|
|
MODE_INFO **mi_8x8,
|
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
|
|
|
BLOCK_SIZE bsize, int *rate, int64_t *dist,
|
|
|
|
int do_recon) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
|
|
|
const int mis = cm->mode_info_stride;
|
|
|
|
int mi_width = num_8x8_blocks_wide_lookup[cpi->sf.always_this_block_size];
|
|
|
|
int mi_height = num_8x8_blocks_high_lookup[cpi->sf.always_this_block_size];
|
|
|
|
int i, j;
|
|
|
|
int chosen_rate = INT_MAX;
|
|
|
|
int64_t chosen_dist = INT_MAX;
|
|
|
|
MB_PREDICTION_MODE mode = DC_PRED;
|
|
|
|
int row8x8_remaining = tile->mi_row_end - mi_row;
|
|
|
|
int col8x8_remaining = tile->mi_col_end - mi_col;
|
|
|
|
int b32i;
|
|
|
|
x->fast_ms = 0;
|
|
|
|
x->subblock_ref = 0;
|
|
|
|
for (b32i = 0; b32i < 4; b32i++) {
|
|
|
|
int b16i;
|
|
|
|
for (b16i = 0; b16i < 4; b16i++) {
|
|
|
|
int b8i;
|
|
|
|
int block_row = get_block_row(b32i, b16i, 0);
|
|
|
|
int block_col = get_block_col(b32i, b16i, 0);
|
|
|
|
int index = block_row * mis + block_col;
|
|
|
|
int rate;
|
|
|
|
int64_t dist;
|
|
|
|
|
|
|
|
int_mv frame_nearest_mv[MAX_REF_FRAMES];
|
|
|
|
int_mv frame_near_mv[MAX_REF_FRAMES];
|
|
|
|
struct buf_2d yv12_mb[MAX_REF_FRAMES][MAX_MB_PLANE];
|
|
|
|
|
|
|
|
// Find a partition size that fits
|
|
|
|
bsize = find_partition_size(cpi->sf.always_this_block_size,
|
|
|
|
(row8x8_remaining - block_row),
|
|
|
|
(col8x8_remaining - block_col),
|
|
|
|
&mi_height, &mi_width);
|
|
|
|
mi_8x8[index] = mi_8x8[0] + index;
|
|
|
|
|
|
|
|
set_mi_row_col(xd, tile, mi_row + block_row, mi_height,
|
|
|
|
mi_col + block_col, mi_width, cm->mi_rows, cm->mi_cols);
|
|
|
|
|
|
|
|
xd->mi_8x8 = mi_8x8 + index;
|
|
|
|
|
|
|
|
if (cm->frame_type != KEY_FRAME) {
|
|
|
|
set_offsets(cpi, tile, mi_row + block_row, mi_col + block_col, bsize);
|
|
|
|
|
|
|
|
vp9_pick_inter_mode(cpi, x, tile,
|
|
|
|
mi_row + block_row, mi_col + block_col,
|
|
|
|
&rate, &dist, cpi->sf.always_this_block_size);
|
|
|
|
} else {
|
|
|
|
set_mode_info(&mi_8x8[index]->mbmi, bsize, mode,
|
|
|
|
mi_row + block_row, mi_col + block_col);
|
|
|
|
vp9_setup_buffer_inter(cpi, x, tile,
|
|
|
|
LAST_FRAME, cpi->sf.always_this_block_size,
|
|
|
|
mi_row + block_row, mi_col + block_col,
|
|
|
|
frame_nearest_mv, frame_near_mv, yv12_mb);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < mi_height; j++)
|
|
|
|
for (i = 0; i < mi_width; i++)
|
|
|
|
if ((xd->mb_to_right_edge >> (3 + MI_SIZE_LOG2)) + mi_width > i
|
|
|
|
&& (xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height > j) {
|
|
|
|
mi_8x8[index+ i + j * mis] = mi_8x8[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (b8i = 0; b8i < 4; b8i++) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
encode_sb_rt(cpi, tile, tp, mi_row, mi_col, 1, BLOCK_64X64);
|
|
|
|
|
|
|
|
*rate = chosen_rate;
|
|
|
|
*dist = chosen_dist;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void encode_rtc_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
int mi_row, TOKENEXTRA **tp) {
|
|
|
|
VP9_COMMON * const cm = &cpi->common;
|
|
|
|
int mi_col;
|
|
|
|
|
|
|
|
// Initialize the left context for the new SB row
|
|
|
|
vpx_memset(&cpi->left_context, 0, sizeof(cpi->left_context));
|
|
|
|
vpx_memset(cpi->left_seg_context, 0, sizeof(cpi->left_seg_context));
|
|
|
|
|
|
|
|
// Code each SB in the row
|
|
|
|
for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
|
|
|
|
mi_col += MI_BLOCK_SIZE) {
|
|
|
|
int dummy_rate;
|
|
|
|
int64_t dummy_dist;
|
|
|
|
|
|
|
|
const int idx_str = cm->mode_info_stride * mi_row + mi_col;
|
|
|
|
MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str;
|
|
|
|
|
|
|
|
cpi->mb.source_variance = UINT_MAX;
|
|
|
|
set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
|
|
|
|
set_partitioning(cpi, tile, mi_8x8, mi_row, mi_col);
|
|
|
|
rtc_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
|
|
|
|
&dummy_rate, &dummy_dist, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void encode_rtc_frame_internal(VP9_COMP *cpi) {
|
|
|
|
int mi_row;
|
|
|
|
MACROBLOCK * const x = &cpi->mb;
|
|
|
|
VP9_COMMON * const cm = &cpi->common;
|
|
|
|
MACROBLOCKD * const xd = &x->e_mbd;
|
|
|
|
|
|
|
|
// fprintf(stderr, "encode_frame_internal frame %d (%d) type %d\n",
|
|
|
|
// cpi->common.current_video_frame, cpi->common.show_frame,
|
|
|
|
// cm->frame_type);
|
|
|
|
|
|
|
|
// debug output
|
|
|
|
#if DBG_PRNT_SEGMAP
|
|
|
|
{
|
|
|
|
FILE *statsfile;
|
|
|
|
statsfile = fopen("segmap2.stt", "a");
|
|
|
|
fprintf(statsfile, "\n");
|
|
|
|
fclose(statsfile);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
vp9_zero(cm->counts.switchable_interp);
|
|
|
|
vp9_zero(cpi->tx_stepdown_count);
|
|
|
|
|
|
|
|
xd->mi_8x8 = cm->mi_grid_visible;
|
|
|
|
// required for vp9_frame_init_quantizer
|
|
|
|
xd->mi_8x8[0] = cm->mi;
|
|
|
|
|
|
|
|
xd->last_mi = cm->prev_mi;
|
|
|
|
|
|
|
|
vp9_zero(cpi->common.counts.mv);
|
|
|
|
vp9_zero(cpi->coef_counts);
|
|
|
|
vp9_zero(cm->counts.eob_branch);
|
|
|
|
|
|
|
|
cpi->mb.e_mbd.lossless = cm->base_qindex == 0 && cm->y_dc_delta_q == 0
|
|
|
|
&& cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0;
|
|
|
|
switch_lossless_mode(cpi, cpi->mb.e_mbd.lossless);
|
|
|
|
|
|
|
|
vp9_frame_init_quantizer(cpi);
|
|
|
|
|
|
|
|
vp9_initialize_rd_consts(cpi);
|
|
|
|
vp9_initialize_me_consts(cpi, cm->base_qindex);
|
|
|
|
switch_tx_mode(cpi);
|
|
|
|
cpi->sf.always_this_block_size = BLOCK_16X16;
|
|
|
|
|
|
|
|
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
|
|
|
|
// Initialize encode frame context.
|
|
|
|
init_encode_frame_mb_context(cpi);
|
|
|
|
|
|
|
|
// Build a frame level activity map
|
|
|
|
build_activity_map(cpi);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Re-initialize encode frame context.
|
|
|
|
init_encode_frame_mb_context(cpi);
|
|
|
|
|
|
|
|
vp9_zero(cpi->rd_comp_pred_diff);
|
|
|
|
vp9_zero(cpi->rd_filter_diff);
|
|
|
|
vp9_zero(cpi->rd_tx_select_diff);
|
|
|
|
vp9_zero(cpi->rd_tx_select_threshes);
|
|
|
|
|
|
|
|
set_prev_mi(cm);
|
|
|
|
|
|
|
|
{
|
|
|
|
struct vpx_usec_timer emr_timer;
|
|
|
|
vpx_usec_timer_start(&emr_timer);
|
|
|
|
|
|
|
|
{
|
|
|
|
// Take tiles into account and give start/end MB
|
|
|
|
int tile_col, tile_row;
|
|
|
|
TOKENEXTRA *tp = cpi->tok;
|
|
|
|
const int tile_cols = 1 << cm->log2_tile_cols;
|
|
|
|
const int tile_rows = 1 << cm->log2_tile_rows;
|
|
|
|
|
|
|
|
for (tile_row = 0; tile_row < tile_rows; tile_row++) {
|
|
|
|
for (tile_col = 0; tile_col < tile_cols; tile_col++) {
|
|
|
|
TileInfo tile;
|
|
|
|
TOKENEXTRA *tp_old = tp;
|
|
|
|
|
|
|
|
// For each row of SBs in the frame
|
|
|
|
vp9_tile_init(&tile, cm, tile_row, tile_col);
|
|
|
|
for (mi_row = tile.mi_row_start;
|
|
|
|
mi_row < tile.mi_row_end; mi_row += 8)
|
|
|
|
encode_rtc_sb_row(cpi, &tile, mi_row, &tp);
|
|
|
|
|
|
|
|
cpi->tok_count[tile_row][tile_col] = (unsigned int)(tp - tp_old);
|
|
|
|
assert(tp - cpi->tok <= get_token_alloc(cm->mb_rows, cm->mb_cols));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vpx_usec_timer_mark(&emr_timer);
|
|
|
|
cpi->time_encode_sb_row += vpx_usec_timer_elapsed(&emr_timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpi->sf.skip_encode_sb) {
|
|
|
|
int j;
|
|
|
|
unsigned int intra_count = 0, inter_count = 0;
|
|
|
|
for (j = 0; j < INTRA_INTER_CONTEXTS; ++j) {
|
|
|
|
intra_count += cm->counts.intra_inter[j][0];
|
|
|
|
inter_count += cm->counts.intra_inter[j][1];
|
|
|
|
}
|
|
|
|
cpi->sf.skip_encode_frame = ((intra_count << 2) < inter_count);
|
|
|
|
cpi->sf.skip_encode_frame &= (cm->frame_type != KEY_FRAME);
|
|
|
|
cpi->sf.skip_encode_frame &= cm->show_frame;
|
|
|
|
} else {
|
|
|
|
cpi->sf.skip_encode_frame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// Keep record of the total distortion this time around for future use
|
|
|
|
cpi->last_frame_distortion = cpi->frame_distortion;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
// end RTC play code
|
|
|
|
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
2012-10-31 01:53:32 +01:00
|
|
|
void vp9_encode_frame(VP9_COMP *cpi) {
|
2014-01-08 23:51:00 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2013-06-06 22:44:34 +02:00
|
|
|
|
2013-06-07 13:29:15 +02:00
|
|
|
// In the longer term the encoder should be generalized to match the
|
|
|
|
// decoder such that we allow compound where one of the 3 buffers has a
|
2013-07-24 16:58:26 +02:00
|
|
|
// different sign bias and that buffer is then the fixed ref. However, this
|
2013-06-07 13:29:15 +02:00
|
|
|
// requires further work in the rd loop. For now the only supported encoder
|
2013-08-20 21:55:41 +02:00
|
|
|
// side behavior is where the ALT ref buffer has opposite sign bias to
|
2013-06-07 13:29:15 +02:00
|
|
|
// the other two.
|
2013-10-03 18:07:24 +02:00
|
|
|
if (!frame_is_intra_only(cm)) {
|
2014-01-10 22:48:44 +01:00
|
|
|
if ((cm->ref_frame_sign_bias[ALTREF_FRAME] ==
|
|
|
|
cm->ref_frame_sign_bias[GOLDEN_FRAME]) ||
|
|
|
|
(cm->ref_frame_sign_bias[ALTREF_FRAME] ==
|
|
|
|
cm->ref_frame_sign_bias[LAST_FRAME])) {
|
2013-10-03 18:07:24 +02:00
|
|
|
cm->allow_comp_inter_inter = 0;
|
|
|
|
} else {
|
|
|
|
cm->allow_comp_inter_inter = 1;
|
|
|
|
cm->comp_fixed_ref = ALTREF_FRAME;
|
|
|
|
cm->comp_var_ref[0] = LAST_FRAME;
|
|
|
|
cm->comp_var_ref[1] = GOLDEN_FRAME;
|
|
|
|
}
|
2013-06-06 22:44:34 +02:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
if (cpi->sf.RD) {
|
2013-12-19 23:28:42 +01:00
|
|
|
int i;
|
|
|
|
REFERENCE_MODE reference_mode;
|
2012-07-14 00:21:29 +02:00
|
|
|
/*
|
|
|
|
* This code does a single RD pass over the whole frame assuming
|
|
|
|
* either compound, single or hybrid prediction as per whatever has
|
|
|
|
* worked best for that type of frame in the past.
|
|
|
|
* It also predicts whether another coding mode would have worked
|
|
|
|
* better that this coding mode. If that is the case, it remembers
|
2012-10-09 18:18:21 +02:00
|
|
|
* that for subsequent frames.
|
|
|
|
* It does the same analysis for transform size selection also.
|
2012-07-14 00:21:29 +02:00
|
|
|
*/
|
2014-01-31 20:08:27 +01:00
|
|
|
const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
|
2013-12-19 23:28:42 +01:00
|
|
|
const int64_t *mode_thresh = cpi->rd_prediction_type_threshes[frame_type];
|
|
|
|
const int64_t *filter_thresh = cpi->rd_filter_threshes[frame_type];
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2012-10-09 18:18:21 +02:00
|
|
|
/* prediction (compound, single or hybrid) mode selection */
|
2013-06-06 22:44:34 +02:00
|
|
|
if (frame_type == 3 || !cm->allow_comp_inter_inter)
|
2013-12-19 23:28:42 +01:00
|
|
|
reference_mode = SINGLE_REFERENCE;
|
|
|
|
else if (mode_thresh[COMPOUND_REFERENCE] > mode_thresh[SINGLE_REFERENCE] &&
|
|
|
|
mode_thresh[COMPOUND_REFERENCE] >
|
|
|
|
mode_thresh[REFERENCE_MODE_SELECT] &&
|
|
|
|
check_dual_ref_flags(cpi) &&
|
|
|
|
cpi->static_mb_pct == 100)
|
|
|
|
reference_mode = COMPOUND_REFERENCE;
|
|
|
|
else if (mode_thresh[SINGLE_REFERENCE] > mode_thresh[REFERENCE_MODE_SELECT])
|
|
|
|
reference_mode = SINGLE_REFERENCE;
|
2012-07-14 00:21:29 +02:00
|
|
|
else
|
2013-12-19 23:28:42 +01:00
|
|
|
reference_mode = REFERENCE_MODE_SELECT;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2014-01-31 20:08:27 +01:00
|
|
|
if (cm->interp_filter == SWITCHABLE) {
|
|
|
|
if (frame_type != ALTREF_FRAME &&
|
|
|
|
filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP] &&
|
|
|
|
filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP_SHARP] &&
|
|
|
|
filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[SWITCHABLE - 1]) {
|
|
|
|
cm->interp_filter = EIGHTTAP_SMOOTH;
|
|
|
|
} else if (filter_thresh[EIGHTTAP_SHARP] > filter_thresh[EIGHTTAP] &&
|
|
|
|
filter_thresh[EIGHTTAP_SHARP] > filter_thresh[SWITCHABLE - 1]) {
|
|
|
|
cm->interp_filter = EIGHTTAP_SHARP;
|
|
|
|
} else if (filter_thresh[EIGHTTAP] > filter_thresh[SWITCHABLE - 1]) {
|
|
|
|
cm->interp_filter = EIGHTTAP;
|
|
|
|
}
|
2013-07-08 23:49:33 +02:00
|
|
|
}
|
|
|
|
|
2013-12-19 23:28:42 +01:00
|
|
|
cpi->mb.e_mbd.lossless = cpi->oxcf.lossless;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
2013-08-20 21:55:41 +02:00
|
|
|
/* transform size selection (4x4, 8x8, 16x16 or select-per-mb) */
|
2013-07-19 20:37:13 +02:00
|
|
|
select_tx_mode(cpi);
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->reference_mode = reference_mode;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
2014-01-31 03:33:26 +01:00
|
|
|
if (cpi->sf.super_fast_rtc)
|
2014-01-29 17:39:39 +01:00
|
|
|
encode_rtc_frame_internal(cpi);
|
|
|
|
else
|
|
|
|
encode_frame_internal(cpi);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-11-23 01:35:37 +01:00
|
|
|
for (i = 0; i < REFERENCE_MODES; ++i) {
|
2014-01-08 23:51:00 +01:00
|
|
|
const int diff = (int) (cpi->rd_comp_pred_diff[i] / cm->MBs);
|
2012-08-10 03:25:29 +02:00
|
|
|
cpi->rd_prediction_type_threshes[frame_type][i] += diff;
|
|
|
|
cpi->rd_prediction_type_threshes[frame_type][i] >>= 1;
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
|
2014-01-08 23:51:00 +01:00
|
|
|
const int64_t diff = cpi->rd_filter_diff[i] / cm->MBs;
|
2013-07-08 23:49:33 +02:00
|
|
|
cpi->rd_filter_threshes[frame_type][i] =
|
|
|
|
(cpi->rd_filter_threshes[frame_type][i] + diff) / 2;
|
|
|
|
}
|
|
|
|
|
2013-07-29 22:38:40 +02:00
|
|
|
for (i = 0; i < TX_MODES; ++i) {
|
2012-10-09 18:18:21 +02:00
|
|
|
int64_t pd = cpi->rd_tx_select_diff[i];
|
|
|
|
int diff;
|
|
|
|
if (i == TX_MODE_SELECT)
|
2014-01-10 22:48:44 +01:00
|
|
|
pd -= RDCOST(cpi->mb.rdmult, cpi->mb.rddiv, 2048 * (TX_SIZES - 1), 0);
|
2014-01-08 23:51:00 +01:00
|
|
|
diff = (int) (pd / cm->MBs);
|
2012-10-09 18:18:21 +02:00
|
|
|
cpi->rd_tx_select_threshes[frame_type][i] += diff;
|
|
|
|
cpi->rd_tx_select_threshes[frame_type][i] /= 2;
|
|
|
|
}
|
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT) {
|
2012-07-14 00:21:29 +02:00
|
|
|
int single_count_zero = 0;
|
|
|
|
int comp_count_zero = 0;
|
|
|
|
|
2013-06-06 22:44:34 +02:00
|
|
|
for (i = 0; i < COMP_INTER_CONTEXTS; i++) {
|
2013-12-17 05:12:47 +01:00
|
|
|
single_count_zero += cm->counts.comp_inter[i][0];
|
|
|
|
comp_count_zero += cm->counts.comp_inter[i][1];
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (comp_count_zero == 0) {
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->reference_mode = SINGLE_REFERENCE;
|
2013-12-17 05:12:47 +01:00
|
|
|
vp9_zero(cm->counts.comp_inter);
|
2012-07-14 00:21:29 +02:00
|
|
|
} else if (single_count_zero == 0) {
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->reference_mode = COMPOUND_REFERENCE;
|
2013-12-17 05:12:47 +01:00
|
|
|
vp9_zero(cm->counts.comp_inter);
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
Dual 16x16 inter prediction.
This patch introduces the concept of dual inter16x16 prediction. A
16x16 inter-predicted macroblock can use 2 references instead of 1,
where both references use the same mvmode (new, near/est, zero). In the
case of newmv, this means that two MVs are coded instead of one. The
frame can be encoded in 3 ways: all MBs single-prediction, all MBs dual
prediction, or per-MB single/dual prediction selection ("hybrid"), in
which case a single bit is coded per-MB to indicate whether the MB uses
single or dual inter prediction.
In the future, we can (maybe?) get further gains by mixing this with
Adrian's 32x32 work, per-segment dual prediction settings, or adding
support for dual splitmv/8x8mv inter prediction.
Gain (on derf-set, CQ mode) is ~2.8% (SSIM) or ~3.6% (glb PSNR). Most
gain is at medium/high bitrates, but there's minor gains at low bitrates
also. Output was confirmed to match between encoder and decoder.
Note for optimization people: this patch introduces a 2nd version of
16x16/8x8 sixtap/bilin functions, which does an avg instead of a
store. They may want to look and make sure this is implemented to
their satisfaction so we can optimize it best in the future.
Change-ID: I59dc84b07cbb3ccf073ac0f756d03d294cb19281
2011-12-06 20:53:02 +01:00
|
|
|
}
|
2012-10-09 18:18:21 +02:00
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
if (cm->tx_mode == TX_MODE_SELECT) {
|
2013-06-06 20:14:04 +02:00
|
|
|
int count4x4 = 0;
|
|
|
|
int count8x8_lp = 0, count8x8_8x8p = 0;
|
|
|
|
int count16x16_16x16p = 0, count16x16_lp = 0;
|
|
|
|
int count32x32 = 0;
|
|
|
|
|
2013-07-23 21:54:04 +02:00
|
|
|
for (i = 0; i < TX_SIZE_CONTEXTS; ++i) {
|
2013-07-24 02:02:08 +02:00
|
|
|
count4x4 += cm->counts.tx.p32x32[i][TX_4X4];
|
|
|
|
count4x4 += cm->counts.tx.p16x16[i][TX_4X4];
|
|
|
|
count4x4 += cm->counts.tx.p8x8[i][TX_4X4];
|
2013-06-06 20:14:04 +02:00
|
|
|
|
2013-07-24 02:02:08 +02:00
|
|
|
count8x8_lp += cm->counts.tx.p32x32[i][TX_8X8];
|
|
|
|
count8x8_lp += cm->counts.tx.p16x16[i][TX_8X8];
|
|
|
|
count8x8_8x8p += cm->counts.tx.p8x8[i][TX_8X8];
|
2013-06-06 20:14:04 +02:00
|
|
|
|
2013-07-24 02:02:08 +02:00
|
|
|
count16x16_16x16p += cm->counts.tx.p16x16[i][TX_16X16];
|
|
|
|
count16x16_lp += cm->counts.tx.p32x32[i][TX_16X16];
|
|
|
|
count32x32 += cm->counts.tx.p32x32[i][TX_32X32];
|
2013-07-23 21:54:04 +02:00
|
|
|
}
|
2012-10-09 18:18:21 +02:00
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0 &&
|
|
|
|
count32x32 == 0) {
|
|
|
|
cm->tx_mode = ALLOW_8X8;
|
|
|
|
reset_skip_txfm_size(cm, TX_8X8);
|
|
|
|
} else if (count8x8_8x8p == 0 && count16x16_16x16p == 0 &&
|
|
|
|
count8x8_lp == 0 && count16x16_lp == 0 && count32x32 == 0) {
|
|
|
|
cm->tx_mode = ONLY_4X4;
|
|
|
|
reset_skip_txfm_size(cm, TX_4X4);
|
32x32 transform for superblocks.
This adds Debargha's DCT/DWT hybrid and a regular 32x32 DCT, and adds
code all over the place to wrap that in the bitstream/encoder/decoder/RD.
Some implementation notes (these probably need careful review):
- token range is extended by 1 bit, since the value range out of this
transform is [-16384,16383].
- the coefficients coming out of the FDCT are manually scaled back by
1 bit, or else they won't fit in int16_t (they are 17 bits). Because
of this, the RD error scoring does not right-shift the MSE score by
two (unlike for 4x4/8x8/16x16).
- to compensate for this loss in precision, the quantizer is halved
also. This is currently a little hacky.
- FDCT and IDCT is double-only right now. Needs a fixed-point impl.
- There are no default probabilities for the 32x32 transform yet; I'm
simply using the 16x16 luma ones. A future commit will add newly
generated probabilities for all transforms.
- No ADST version. I don't think we'll add one for this level; if an
ADST is desired, transform-size selection can scale back to 16x16
or lower, and use an ADST at that level.
Additional notes specific to Debargha's DWT/DCT hybrid:
- coefficient scale is different for the top/left 16x16 (DCT-over-DWT)
block than for the rest (DWT pixel differences) of the block. Therefore,
RD error scoring isn't easily scalable between coefficient and pixel
domain. Thus, unfortunately, we need to compute the RD distortion in
the pixel domain until we figure out how to scale these appropriately.
Change-Id: I00386f20f35d7fabb19aba94c8162f8aee64ef2b
2012-12-07 23:45:05 +01:00
|
|
|
} else if (count8x8_lp == 0 && count16x16_lp == 0 && count4x4 == 0) {
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->tx_mode = ALLOW_32X32;
|
32x32 transform for superblocks.
This adds Debargha's DCT/DWT hybrid and a regular 32x32 DCT, and adds
code all over the place to wrap that in the bitstream/encoder/decoder/RD.
Some implementation notes (these probably need careful review):
- token range is extended by 1 bit, since the value range out of this
transform is [-16384,16383].
- the coefficients coming out of the FDCT are manually scaled back by
1 bit, or else they won't fit in int16_t (they are 17 bits). Because
of this, the RD error scoring does not right-shift the MSE score by
two (unlike for 4x4/8x8/16x16).
- to compensate for this loss in precision, the quantizer is halved
also. This is currently a little hacky.
- FDCT and IDCT is double-only right now. Needs a fixed-point impl.
- There are no default probabilities for the 32x32 transform yet; I'm
simply using the 16x16 luma ones. A future commit will add newly
generated probabilities for all transforms.
- No ADST version. I don't think we'll add one for this level; if an
ADST is desired, transform-size selection can scale back to 16x16
or lower, and use an ADST at that level.
Additional notes specific to Debargha's DWT/DCT hybrid:
- coefficient scale is different for the top/left 16x16 (DCT-over-DWT)
block than for the rest (DWT pixel differences) of the block. Therefore,
RD error scoring isn't easily scalable between coefficient and pixel
domain. Thus, unfortunately, we need to compute the RD distortion in
the pixel domain until we figure out how to scale these appropriately.
Change-Id: I00386f20f35d7fabb19aba94c8162f8aee64ef2b
2012-12-07 23:45:05 +01:00
|
|
|
} else if (count32x32 == 0 && count8x8_lp == 0 && count4x4 == 0) {
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->tx_mode = ALLOW_16X16;
|
|
|
|
reset_skip_txfm_size(cm, TX_16X16);
|
2012-10-09 18:18:21 +02:00
|
|
|
}
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
} else {
|
2014-01-31 20:08:27 +01:00
|
|
|
// Force the usage of the BILINEAR interp_filter.
|
|
|
|
cm->interp_filter = BILINEAR;
|
2014-01-31 03:33:26 +01:00
|
|
|
if (cpi->sf.super_fast_rtc)
|
|
|
|
encode_rtc_frame_internal(cpi);
|
|
|
|
else
|
|
|
|
encode_frame_internal(cpi);
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
Dual 16x16 inter prediction.
This patch introduces the concept of dual inter16x16 prediction. A
16x16 inter-predicted macroblock can use 2 references instead of 1,
where both references use the same mvmode (new, near/est, zero). In the
case of newmv, this means that two MVs are coded instead of one. The
frame can be encoded in 3 ways: all MBs single-prediction, all MBs dual
prediction, or per-MB single/dual prediction selection ("hybrid"), in
which case a single bit is coded per-MB to indicate whether the MB uses
single or dual inter prediction.
In the future, we can (maybe?) get further gains by mixing this with
Adrian's 32x32 work, per-segment dual prediction settings, or adding
support for dual splitmv/8x8mv inter prediction.
Gain (on derf-set, CQ mode) is ~2.8% (SSIM) or ~3.6% (glb PSNR). Most
gain is at medium/high bitrates, but there's minor gains at low bitrates
also. Output was confirmed to match between encoder and decoder.
Note for optimization people: this patch introduces a 2nd version of
16x16/8x8 sixtap/bilin functions, which does an avg instead of a
store. They may want to look and make sure this is implemented to
their satisfaction so we can optimize it best in the future.
Change-ID: I59dc84b07cbb3ccf073ac0f756d03d294cb19281
2011-12-06 20:53:02 +01:00
|
|
|
}
|
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi) {
|
2013-08-22 01:25:02 +02:00
|
|
|
const MB_PREDICTION_MODE y_mode = mi->mbmi.mode;
|
|
|
|
const MB_PREDICTION_MODE uv_mode = mi->mbmi.uv_mode;
|
2013-08-27 20:05:08 +02:00
|
|
|
const BLOCK_SIZE bsize = mi->mbmi.sb_type;
|
2013-08-22 01:25:02 +02:00
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
++counts->uv_mode[y_mode][uv_mode];
|
2013-08-22 01:25:02 +02:00
|
|
|
|
|
|
|
if (bsize < BLOCK_8X8) {
|
2013-05-20 21:08:22 +02:00
|
|
|
int idx, idy;
|
2013-08-22 01:25:02 +02:00
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
|
|
|
|
for (idy = 0; idy < 2; idy += num_4x4_blocks_high)
|
|
|
|
for (idx = 0; idx < 2; idx += num_4x4_blocks_wide)
|
2014-01-10 22:48:44 +01:00
|
|
|
++counts->y_mode[0][mi->bmi[idy * 2 + idx].as_mode];
|
2013-08-22 01:25:02 +02:00
|
|
|
} else {
|
2014-01-10 22:48:44 +01:00
|
|
|
++counts->y_mode[size_group_lookup[bsize]][y_mode];
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
2011-05-12 18:01:55 +02:00
|
|
|
|
|
|
|
// Experimental stub function to create a per MB zbin adjustment based on
|
|
|
|
// some previously calculated measure of MB activity.
|
2012-10-31 01:53:32 +01:00
|
|
|
static void adjust_act_zbin(VP9_COMP *cpi, MACROBLOCK *x) {
|
2011-06-08 17:00:59 +02:00
|
|
|
#if USE_ACT_INDEX
|
2012-07-14 00:21:29 +02:00
|
|
|
x->act_zbin_adj = *(x->mb_activity_ptr);
|
2011-06-08 17:00:59 +02:00
|
|
|
#else
|
2012-07-14 00:21:29 +02:00
|
|
|
int64_t a;
|
|
|
|
int64_t b;
|
|
|
|
int64_t act = *(x->mb_activity_ptr);
|
|
|
|
|
|
|
|
// Apply the masking to the RD multiplier.
|
|
|
|
a = act + 4 * cpi->activity_avg;
|
|
|
|
b = 4 * act + cpi->activity_avg;
|
|
|
|
|
|
|
|
if (act > cpi->activity_avg)
|
2013-06-19 23:26:49 +02:00
|
|
|
x->act_zbin_adj = (int) (((int64_t) b + (a >> 1)) / a) - 1;
|
2012-07-14 00:21:29 +02:00
|
|
|
else
|
2013-06-19 23:26:49 +02:00
|
|
|
x->act_zbin_adj = 1 - (int) (((int64_t) a + (b >> 1)) / b);
|
2011-06-08 17:00:59 +02:00
|
|
|
#endif
|
2011-05-12 18:01:55 +02:00
|
|
|
}
|
2013-12-18 19:39:08 +01:00
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
static int get_zbin_mode_boost(const MB_MODE_INFO *mbmi, int enabled) {
|
2013-12-18 19:39:08 +01:00
|
|
|
if (enabled) {
|
|
|
|
if (is_inter_block(mbmi)) {
|
|
|
|
if (mbmi->mode == ZEROMV) {
|
|
|
|
return mbmi->ref_frame[0] != LAST_FRAME ? GF_ZEROMV_ZBIN_BOOST
|
|
|
|
: LF_ZEROMV_ZBIN_BOOST;
|
|
|
|
} else {
|
|
|
|
return mbmi->sb_type < BLOCK_8X8 ? SPLIT_MV_ZBIN_BOOST
|
|
|
|
: MV_ZBIN_BOOST;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return INTRA_ZBIN_BOOST;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled,
|
2013-08-27 20:05:08 +02:00
|
|
|
int mi_row, int mi_col, BLOCK_SIZE bsize) {
|
2014-01-10 22:48:44 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO **mi_8x8 = xd->mi_8x8;
|
|
|
|
MODE_INFO *mi = mi_8x8[0];
|
2013-05-21 00:59:39 +02:00
|
|
|
MB_MODE_INFO *mbmi = &mi->mbmi;
|
2013-11-06 06:07:08 +01:00
|
|
|
PICK_MODE_CONTEXT *ctx = get_block_context(x, bsize);
|
2013-05-21 00:59:39 +02:00
|
|
|
unsigned int segment_id = mbmi->segment_id;
|
2013-01-06 03:20:25 +01:00
|
|
|
const int mis = cm->mode_info_stride;
|
2013-07-23 15:51:44 +02:00
|
|
|
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
const int mi_height = num_8x8_blocks_high_lookup[bsize];
|
2013-11-22 18:21:53 +01:00
|
|
|
x->skip_recode = !x->select_txfm_size && mbmi->sb_type >= BLOCK_8X8 &&
|
2014-01-29 17:39:39 +01:00
|
|
|
(cpi->oxcf.aq_mode != COMPLEXITY_AQ) &&
|
2014-01-31 03:33:26 +01:00
|
|
|
!cpi->sf.super_fast_rtc;
|
2013-11-06 06:07:08 +01:00
|
|
|
x->skip_optimize = ctx->is_coded;
|
|
|
|
ctx->is_coded = 1;
|
2013-08-08 00:22:51 +02:00
|
|
|
x->use_lp32x32fdct = cpi->sf.use_lp32x32fdct;
|
2013-07-09 01:48:47 +02:00
|
|
|
x->skip_encode = (!output_enabled && cpi->sf.skip_encode_frame &&
|
2013-11-13 02:28:27 +01:00
|
|
|
x->q_index < QIDX_SKIP_THRESH);
|
2013-07-09 01:48:47 +02:00
|
|
|
if (x->skip_encode)
|
|
|
|
return;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
|
|
|
if (cm->frame_type == KEY_FRAME) {
|
|
|
|
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
|
|
|
|
adjust_act_zbin(cpi, x);
|
|
|
|
vp9_update_zbin_extra(cpi, x);
|
|
|
|
}
|
|
|
|
} else {
|
2014-01-28 01:00:20 +01:00
|
|
|
set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
|
2014-01-27 23:20:39 +01:00
|
|
|
xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
|
2013-01-06 03:20:25 +01:00
|
|
|
|
|
|
|
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
|
|
|
|
// Adjust the zbin based on this MB rate.
|
|
|
|
adjust_act_zbin(cpi, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Experimental code. Special case for gf and arf zeromv modes.
|
|
|
|
// Increase zbin size to suppress noise
|
2013-12-18 19:39:08 +01:00
|
|
|
cpi->zbin_mode_boost = get_zbin_mode_boost(mbmi,
|
|
|
|
cpi->zbin_mode_boost_enabled);
|
2013-01-06 03:20:25 +01:00
|
|
|
vp9_update_zbin_extra(cpi, x);
|
|
|
|
}
|
|
|
|
|
2013-08-23 00:50:51 +02:00
|
|
|
if (!is_inter_block(mbmi)) {
|
2014-01-15 02:58:25 +01:00
|
|
|
mbmi->skip_coeff = 1;
|
2013-08-16 21:51:20 +02:00
|
|
|
vp9_encode_intra_block_y(x, MAX(bsize, BLOCK_8X8));
|
|
|
|
vp9_encode_intra_block_uv(x, MAX(bsize, BLOCK_8X8));
|
2013-01-06 03:20:25 +01:00
|
|
|
if (output_enabled)
|
2014-01-10 22:48:44 +01:00
|
|
|
sum_intra_stats(&cm->counts, mi);
|
2012-11-08 20:03:00 +01:00
|
|
|
} else {
|
2014-01-03 21:50:57 +01:00
|
|
|
int ref;
|
|
|
|
const int is_compound = has_second_ref(mbmi);
|
|
|
|
for (ref = 0; ref < 1 + is_compound; ++ref) {
|
2014-01-06 23:50:54 +01:00
|
|
|
YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi,
|
|
|
|
mbmi->ref_frame[ref]);
|
2013-12-28 03:44:19 +01:00
|
|
|
setup_pre_planes(xd, ref, cfg, mi_row, mi_col, &xd->block_refs[ref]->sf);
|
2013-05-21 00:59:39 +02:00
|
|
|
}
|
2013-08-06 00:23:49 +02:00
|
|
|
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, MAX(bsize, BLOCK_8X8));
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
|
2013-08-23 00:50:51 +02:00
|
|
|
if (!is_inter_block(mbmi)) {
|
2013-08-06 00:23:49 +02:00
|
|
|
vp9_tokenize_sb(cpi, t, !output_enabled, MAX(bsize, BLOCK_8X8));
|
2013-05-05 07:09:43 +02:00
|
|
|
} else if (!x->skip) {
|
2014-01-15 02:58:25 +01:00
|
|
|
mbmi->skip_coeff = 1;
|
2013-08-16 21:51:20 +02:00
|
|
|
vp9_encode_sb(x, MAX(bsize, BLOCK_8X8));
|
2013-08-06 00:23:49 +02:00
|
|
|
vp9_tokenize_sb(cpi, t, !output_enabled, MAX(bsize, BLOCK_8X8));
|
2013-01-10 17:23:59 +01:00
|
|
|
} else {
|
2013-08-13 18:47:40 +02:00
|
|
|
mbmi->skip_coeff = 1;
|
2013-04-09 19:54:19 +02:00
|
|
|
if (output_enabled)
|
2014-01-29 23:48:42 +01:00
|
|
|
cm->counts.skip[vp9_get_skip_context(xd)][1]++;
|
2013-08-12 20:24:24 +02:00
|
|
|
reset_skip_context(xd, MAX(bsize, BLOCK_8X8));
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (output_enabled) {
|
2013-07-19 20:37:13 +02:00
|
|
|
if (cm->tx_mode == TX_MODE_SELECT &&
|
2013-08-06 00:23:49 +02:00
|
|
|
mbmi->sb_type >= BLOCK_8X8 &&
|
2013-08-03 01:25:33 +02:00
|
|
|
!(is_inter_block(mbmi) &&
|
2013-08-13 18:47:40 +02:00
|
|
|
(mbmi->skip_coeff ||
|
2013-08-14 20:20:33 +02:00
|
|
|
vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)))) {
|
2013-12-07 00:31:06 +01:00
|
|
|
++get_tx_counts(max_txsize_lookup[bsize], vp9_get_tx_size_context(xd),
|
|
|
|
&cm->counts.tx)[mbmi->tx_size];
|
2013-01-06 03:20:25 +01:00
|
|
|
} else {
|
|
|
|
int x, y;
|
2013-12-05 21:25:03 +01:00
|
|
|
TX_SIZE tx_size;
|
2013-06-19 23:26:49 +02:00
|
|
|
// The new intra coding scheme requires no change of transform size
|
2013-08-03 01:25:33 +02:00
|
|
|
if (is_inter_block(&mi->mbmi)) {
|
2013-12-05 21:25:03 +01:00
|
|
|
tx_size = MIN(tx_mode_to_biggest_tx_size[cm->tx_mode],
|
|
|
|
max_txsize_lookup[bsize]);
|
2013-05-17 21:50:40 +02:00
|
|
|
} else {
|
2013-12-05 21:25:03 +01:00
|
|
|
tx_size = (bsize >= BLOCK_8X8) ? mbmi->tx_size : TX_4X4;
|
2013-05-17 21:50:40 +02:00
|
|
|
}
|
2013-04-10 06:28:27 +02:00
|
|
|
|
2013-08-28 04:47:53 +02:00
|
|
|
for (y = 0; y < mi_height; y++)
|
|
|
|
for (x = 0; x < mi_width; x++)
|
|
|
|
if (mi_col + x < cm->mi_cols && mi_row + y < cm->mi_rows)
|
2013-12-05 21:25:03 +01:00
|
|
|
mi_8x8[mis * y + x]->mbmi.tx_size = tx_size;
|
2012-11-08 20:03:00 +01:00
|
|
|
}
|
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|