Compare commits

...

32 Commits

Author SHA1 Message Date
Jingning Han
9d9b70a36a Allow backward prob update in external mode info coding flow
This commit enables vpxenc to properly count the coded motion
vector related information for backward update. This allows the
coding flow using external mode info to use backward probability
update. In the short test clip, over 10% bit-rate saving is
observed at no distortion change.

Change-Id: Ie27e97114ab91c3d95ba7b5554d617d226db5e20
2014-07-21 12:11:31 -07:00
Jingning Han
1e168d12d9 Enable motion vector based prediction mode decision
This commit enables vpxenc to compare the motion vector provided
by external file to the predicted motion vectors and select the
prediction mode with minimum rate cost if motion vector is matched.
It doesn't change reconstruction distortion, but provide rate
savings.

Change-Id: Ia682b775d2bafcaabb5a113bd90a98e1931c9c5a
2014-07-17 16:35:11 -07:00
Jingning Han
6ee6e714b4 Make key frame coding mode configurable in the command line
Add --kf-extc configuration. If it is 1, the key frame is coded
using mode info from external file; otherwise, use vpxenc internal
mode selection process to decide coding modes. It is by default 0.

Change-Id: I916f811f9eaa2d0f6cc2a2035ca381a1b0ddd974
2014-07-17 11:52:21 -07:00
Jingning Han
674cc787d3 Update the effective motion vector of sub8x8 blocks
This commit enables the vpxenc to update the effective motion
vectors stored in the mode_info struct for sub8x8 block coding. It
resolves the reference motion vector enc/dec mismatch issue.

Change-Id: I93a88fed6f15fad06a41ca21e297d7281cb75c57
2014-07-16 21:37:15 -07:00
Jingning Han
c765cd1a78 Properly handle the effective motion vector in inferred mv modes
This commit allows vpxenc to properly set the effective motion
vector values in the mode_info struct for inferred motion vector
modes. It resolves an enc/dec mismatch issue due to the mode info
struct loaded from external file has conflict effective motion
vector and inferred prediction mode.

Change-Id: I1f47aeaf2b92fcd4dd3d4f3644b88466495be070
2014-07-16 21:35:29 -07:00
Jingning Han
9e3965ae90 Make external sub8x8 block mode info conformable coding decisions
This commit converts the sub8x8 block mode info from external file
into proper format that conforms the bit-stream definitions. It
resolves an enc/dec mismatch issue in sub8x8 block coding used in
the inter frames.

Change-Id: Ie5717b19d0d06e0f525f9b7c7311abdd40f7885f
2014-07-15 22:40:33 -07:00
Jingning Han
f297504f2d Re-work configure interface for encoding based on external mi
This commit refines the configuration interface for encoding
process based on external mode info. It allows the vpxenc to read
the external file name from command line, and to produce warning
message when necessary.

Change-Id: I109d02ea9e6e418d00378d512ed9ab9bb0770dbd
2014-07-14 15:30:03 -07:00
Jingning Han
b4b897605a Allow more coding flexibility in key frame coding
This commit relaxes the encoding mode constraints on key frame
coding. It improves the key frame coding performance in speed 5 and
up.

Change-Id: I114315c2b467174bb1f135f4ab2c1f328c8c65be
2014-07-11 09:55:38 -07:00
Jingning Han
51959786d2 Merge "Use normal encoding route for key frame coding" into sandbox/Jingning/transcode 2014-07-10 10:55:24 -07:00
Jingning Han
502baedb48 Enable motion vector precision regulation conversion
This commit allows the vpxenc to check if the motion vectors read
from external file comply the frame header. If the frame is using
lower precision, the codec will convert the non-conformable motion
vectors into corresponding level.

This fixes another outstanding enc/dec mismatch issue due to the
mode_info values provided by external file not complying the
bit-stream definitions.

Change-Id: Ie5409f5d3201e9159f6a49c7608db3541f8a190c
2014-07-09 16:58:44 -07:00
Jingning Han
2568ff0081 Enforce tx_size conversion to handle invalid mode_info values
This commit forces a transform size check to handle the case where
the provided transform size is larger than the block size. In such
cases, it will convert the transform size to be the maximally
allowed value according to the block size.

Change-Id: I6ae26d5008fd60955427e2b7d5dcd3daa6eeb531
2014-07-09 10:31:41 -07:00
Jingning Han
4f2aeceabe Use normal encoding route for key frame coding
This commit makes the key frame coding to use the normal vpxenc
coding route. The encoding process based on mode_info read from
external file now starts from the first inter frame.

Change-Id: Iee5ae2c3aa35d4b89d0cb4e890b9b0f29fe89d62
2014-07-08 12:06:31 -07:00
Jim Bankoski
06eed502bd adjust the context we got from file
Change-Id: Ifeed2fa6b8dbc735f3746548e4535d522e732990
2014-07-07 16:03:32 -07:00
Jingning Han
5e9f681dec Merge "Force the use of selectable transform size" into sandbox/Jingning/transcode 2014-07-01 10:51:15 -07:00
Jingning Han
80bd67f09d Merge "Disable decoder read/write access to the mode_info array" into sandbox/Jingning/transcode 2014-07-01 10:32:07 -07:00
Jingning Han
d019119777 Force the use of selectable transform size
Change-Id: I87034c5933a9cfc6f82b925bcae11a2e6509c472
2014-06-30 17:17:31 -07:00
Jingning Han
6af2a29764 Disable decoder read/write access to the mode_info array
The decoder read/write access to the mode_info array was for the
purpose of creating a conformable coding mode decisions and hence
validating the encoding process based on exteranl mode_info
array. This commit makes a flag to disable all such potential access.

Change-Id: I21ece4b595c1c24cdf5581a3147fe76bf33a5570
2014-06-30 14:49:15 -07:00
Jingning Han
a3d2b5213e Merge "Enable vpxenc to process and convert external mode_info" into sandbox/Jingning/transcode 2014-06-30 11:15:53 -07:00
Jingning Han
0d075d907c Merge "Add optional mode_info printout function for debug purpose" into sandbox/Jingning/transcode 2014-06-27 16:34:42 -07:00
Jingning Han
1bf27df775 Enable vpxenc to process and convert external mode_info
This commit enables the encoder to convert the mode information
read from external file into effective VP9 coding decisions. Further
optimization for compression performance can be applied therein.

Change-Id: Ic3abb8e223ed4b5aa54e5ed099feb450c1ad9363
2014-06-27 16:10:26 -07:00
Jingning Han
d7e8490d04 Add optional mode_info printout function for debug purpose
This commit adds an optional function to print out the mode_info
loaded from external file for debug purpose. It can be turned on
by setting PRINT_MODE_INFO_LOAD 1.

Change-Id: I8612801cbf2eb38213105afb7434da2584b3ff2c
2014-06-26 12:11:44 -07:00
Jingning Han
68556c2f1d Merge "Silence quantization index check warnings" into sandbox/Jingning/transcode 2014-06-19 14:37:23 -07:00
Jingning Han
19c1c1f429 Merge "Make encoding process support non-switchable filter" into sandbox/Jingning/transcode 2014-06-19 14:37:05 -07:00
Jingning Han
1153454cd0 Merge "Enable encoding and bit-stream writing based on mode_info array" into sandbox/Jingning/transcode 2014-06-19 14:36:37 -07:00
Jingning Han
8f17deb617 Merge "Dump mode_info array from vp9 decoder to external file" into sandbox/Jingning/transcode 2014-06-19 14:36:20 -07:00
Jingning Han
f5bb406799 Merge "Add transcode flag in the experimental list" into sandbox/Jingning/transcode 2014-06-19 14:36:09 -07:00
Jingning Han
ff073a70ee Silence quantization index check warnings
Allow the encoder to use fixed quantization step size. Note that
this effectively breaks the internal rate control scheme and
can cause substantial compression performance.

Change-Id: I1caacb1ab06629107f8975e5f707de16d6d5b36a
2014-06-19 09:52:09 -07:00
Jingning Han
44877260a5 Make encoding process support non-switchable filter
This commit allows the encoder to handle cases where the encoder
is forced to use an arbitrary prediction filter type.

Change-Id: I984e554ef8b05d88d3c1714c0b621f5cf09f5dd6
2014-06-17 15:03:49 -07:00
Jingning Han
06510d1ff9 Enable encoding and bit-stream writing based on mode_info array
This commit enables vpxenc to encode and write out bit-stream from
coding information provided by external mode_info array file. It
currently assumes single reference frame and 8-tap switchable
prediction filters at frame header level.

Tested using the mode_info array dumped at VP9 decoder into the
external file, where the bit-stream was generated by VP9 encoder
at speed -6. The coding statics remain the same.

Note that the compression performance will be affected quite a lot
in the two pass coding setting, where at this point the rate
control scheme can not be updated properly without statistics
gathered during rate distortion optimization search.

Change-Id: Ide979d08d3ce6167c1f2e513c34fd8440f3e2aaf
2014-06-17 14:57:43 -07:00
Jingning Han
b95807f2bb Dump mode_info array from vp9 decoder to external file
This commit allows the vp9 decoder to dump the decoded mode_info
array, per 64x64, into external file, which serves as conformable
test vector for transcoding encoder. The mode_info of 8x8 block
inside a 64x64 block is aligned in raster order.

Change-Id: I0447d62922c674a674c0d4b31184625cf722f872
2014-06-11 15:26:42 -07:00
Jingning Han
de810ac620 Add transcode flag in the experimental list
Change-Id: I756b5899d3b5101643b4e084a1647a15b427d9e9
2014-06-11 11:45:46 -07:00
Jingning Han
0b3ffed9be Add transcode flag in the experimental list
Change-Id: I756b5899d3b5101643b4e084a1647a15b427d9e9
2014-06-11 11:18:02 -07:00
16 changed files with 412 additions and 8 deletions

1
configure vendored
View File

@@ -271,6 +271,7 @@ EXPERIMENT_LIST="
alpha
multiple_arf
spatial_svc
transcode
"
CONFIG_LIST="
external_build

View File

@@ -212,6 +212,10 @@ typedef struct VP9Common {
PARTITION_CONTEXT *above_seg_context;
ENTROPY_CONTEXT *above_context;
#if CONFIG_TRANSCODE
FILE *mi_array_pf;
#endif
} VP9_COMMON;
static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {

View File

@@ -312,6 +312,13 @@ static MB_MODE_INFO *set_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd,
for (x = !y; x < x_mis; ++x)
xd->mi[y * cm->mi_stride + x] = xd->mi[0];
#if CONFIG_TRANSCODE && WRITE_MI_ARRAY
for (y = 0; y < y_mis; ++y)
for (x = !y; x < x_mis; ++x)
vpx_memcpy(&cm->mi[offset + y * cm->mi_stride + x],
&cm->mi[offset], sizeof(MODE_INFO));
#endif
set_skip_context(xd, mi_row, mi_col);
// Distance of Mb to the various image edges. These are specified to 8th pel
@@ -412,6 +419,34 @@ static void decode_partition(VP9_COMMON *const cm, MACROBLOCKD *const xd,
PARTITION_TYPE partition;
BLOCK_SIZE subsize;
#if CONFIG_TRANSCODE && READ_MI_ARRAY
// This is for test purpose only. It verifies the external file
// contains the right mode_info array.
if (bsize == BLOCK_64X64) {
MODE_INFO mi_array[64];
FILE *pf = cm->mi_array_pf;
if (pf) {
int i, j;
for (j = 0; j < MI_BLOCK_SIZE; ++j)
for (i = 0; i < MI_BLOCK_SIZE; ++i)
fread(&mi_array[j * 8 + i], 1, sizeof(MODE_INFO), pf);
}
if (pf && mi_row == 0 && mi_col == 8) {
int i, j;
for (j = 0; j < MI_BLOCK_SIZE; ++j) {
for (i = 0; i < MI_BLOCK_SIZE; ++i) {
MB_MODE_INFO *mbmi = &mi_array[j * 8 + i].mbmi;
b_mode_info *bmi = mi_array[j * 8 + i].bmi;
fprintf(stderr, "pos (%d, %d), bsize %d, mode %d\n",
mi_row + j , mi_col + i, mbmi->sb_type, bmi[0].as_mode);
}
}
fprintf(stderr, "\n");
}
}
#endif
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
return;
@@ -449,6 +484,22 @@ static void decode_partition(VP9_COMMON *const cm, MACROBLOCKD *const xd,
if (bsize >= BLOCK_8X8 &&
(bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
update_partition_context(xd, mi_row, mi_col, subsize, bsize);
#if CONFIG_TRANSCODE && WRITE_MI_ARRAY
if (bsize == BLOCK_64X64) {
FILE *pf = cm->mi_array_pf;
if (pf) {
int i, j;
int offset = mi_row * cm->mi_stride + mi_col;
for (j = 0; j < MI_BLOCK_SIZE; ++j)
for (i = 0; i < MI_BLOCK_SIZE; ++i)
fwrite(&cm->mi[offset + j * cm->mi_stride + i],
1, sizeof(MODE_INFO), pf);
} else {
assert(0);
}
}
#endif
}
static void setup_token_decoder(const uint8_t *data,

View File

@@ -497,6 +497,10 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
mi->bmi[j + 2] = mi->bmi[j];
if (num_4x4_w == 2)
mi->bmi[j + 1] = mi->bmi[j];
#if CONFIG_TRANSCODE
mi->bmi[j].as_mode = b_mode;
#endif
}
}

View File

@@ -32,6 +32,8 @@
#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/decoder/vp9_dthread.h"
#include <stdio.h>
static void initialize_dec() {
static int init_done = 0;
@@ -79,6 +81,9 @@ VP9Decoder *vp9_decoder_create() {
vp9_worker_init(&pbi->lf_worker);
#if CONFIG_TRANSCODE && WRITE_MI_ARRAY
cm->mi_array_pf = fopen("mode_info_array_2.bin", "rb");
#endif
return pbi;
}
@@ -86,6 +91,10 @@ void vp9_decoder_remove(VP9Decoder *pbi) {
VP9_COMMON *const cm = &pbi->common;
int i;
#if CONFIG_TRANSCODE && WRITE_MI_ARRAY
fclose(cm->mi_array_pf);
#endif
vp9_remove_common(cm);
vp9_worker_end(&pbi->lf_worker);
vpx_free(pbi->lf_worker.data1);

View File

@@ -27,6 +27,11 @@
extern "C" {
#endif
#if CONFIG_TRANSCODE
#define WRITE_MI_ARRAY 0
#define READ_MI_ARRAY 0
#endif
// TODO(hkuang): combine this with TileWorkerData.
typedef struct TileData {
VP9_COMMON *cm;

View File

@@ -100,10 +100,15 @@ void vp9_setup_pc_tree(VP9_COMMON *cm, VP9_COMP *cpi) {
vpx_free(cpi->leaf_tree);
CHECK_MEM_ERROR(cm, cpi->leaf_tree, vpx_calloc(leaf_nodes,
sizeof(*cpi->leaf_tree)));
#if CONFIG_TRANSCODE
vpx_memset(cpi->leaf_tree, 0, sizeof(*cpi->leaf_tree));
#endif
vpx_free(cpi->pc_tree);
CHECK_MEM_ERROR(cm, cpi->pc_tree, vpx_calloc(tree_nodes,
sizeof(*cpi->pc_tree)));
#if CONFIG_TRANSCODE
vpx_memset(cpi->pc_tree, 0, sizeof(*cpi->pc_tree));
#endif
this_pc = &cpi->pc_tree[0];
this_leaf = &cpi->leaf_tree[0];

View File

@@ -547,6 +547,115 @@ static void choose_partitioning(VP9_COMP *cpi,
}
}
#if CONFIG_TRANSCODE
// TODO(jingning) This is the place where the encoder reads preliminary
// coding mode information from external file, and converts them into
// effective VP9 conformable coding decisions. Certain optimization work
// may be applied herein.
static void mode_info_conversion(VP9_COMP *cpi, const TileInfo *const tile,
MACROBLOCK *x, int mi_row, int mi_col) {
VP9_COMMON *cm = &cpi->common;
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
MV_REFERENCE_FRAME ref_frame = mbmi->ref_frame[0];
int_mv nearest_mv, near_mv;
int_mv *candidates = mbmi->ref_mvs[ref_frame];
// TODO(jingning) handle single reference frame only
mbmi->ref_frame[1] = NONE;
vp9_find_mv_refs(cm, xd, tile, xd->mi[0], ref_frame, candidates,
mi_row, mi_col);
vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv, candidates,
&nearest_mv, &near_mv);
if (!cm->allow_high_precision_mv || !vp9_use_mv_hp(&mbmi->mv[0].as_mv)) {
if (mbmi->mv[0].as_mv.row & 1)
mbmi->mv[0].as_mv.row += (mbmi->mv[0].as_mv.row > 0 ? -1 : 1);
if (mbmi->mv[0].as_mv.col & 1)
mbmi->mv[0].as_mv.col += (mbmi->mv[1].as_mv.col > 0 ? -1 : 1);
}
if (cm->tx_mode != TX_MODE_SELECT) {
mbmi->tx_size = MIN(max_txsize_lookup[mbmi->sb_type],
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
} else if (mbmi->tx_size > max_txsize_lookup[mbmi->sb_type]) {
mbmi->tx_size = max_txsize_lookup[mbmi->sb_type];
}
if (cm->interp_filter != SWITCHABLE)
mbmi->interp_filter = cm->interp_filter;
if (!is_inter_block(mbmi)) {
mbmi->mv[0].as_int = 0;
mbmi->mv[1].as_int = 0;
}
if (mbmi->sb_type < BLOCK_8X8) {
MODE_INFO *mi = xd->mi[0];
const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi->sb_type]; // 1 or 2
const int num_4x4_h = num_4x4_blocks_high_lookup[mbmi->sb_type]; // 1 or 2
int idx, idy;
for (idy = 0; idy < 2; idy += num_4x4_h) {
for (idx = 0; idx < 2; idx += num_4x4_w) {
const int j = idy * 2 + idx;
int ref;
PREDICTION_MODE b_mode = mi->bmi[j].as_mode;
for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, j, ref, mi_row, mi_col,
&nearest_mv, &near_mv);
if (b_mode > TM_PRED) {
// inter mode
if (mi->bmi[j].as_mv[ref].as_int == nearest_mv.as_int)
b_mode = NEARESTMV;
else if (mi->bmi[j].as_mv[ref].as_int == near_mv.as_int)
b_mode = NEARMV;
else if (mi->bmi[j].as_mv[ref].as_int == 0)
b_mode = ZEROMV;
} else {
// intra mode
mi->bmi[j].as_mv[ref].as_int = 0;
}
mi->bmi[j].as_mode = b_mode;
}
if (num_4x4_h == 2)
mi->bmi[j + 2] = mi->bmi[j];
if (num_4x4_w == 2)
mi->bmi[j + 1] = mi->bmi[j];
}
}
mbmi->mode = mi->bmi[3].as_mode;
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;
} else {
if (mbmi->mode > TM_PRED) {
if (mbmi->mv[0].as_int == nearest_mv.as_int)
mbmi->mode = NEARESTMV;
else if (mbmi->mv[0].as_int == near_mv.as_int)
mbmi->mode = NEARMV;
else if (mbmi->mv[0].as_int == 0)
mbmi->mode = ZEROMV;
}
}
if (is_inter_block(mbmi)) {
vp9_update_mv_count(cm, xd);
if (cm->interp_filter == SWITCHABLE) {
const int ctx = vp9_get_pred_context_switchable_interp(xd);
++cm->counts.switchable_interp[ctx][mbmi->interp_filter];
}
}
}
#endif
static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
int mi_row, int mi_col, BLOCK_SIZE bsize,
int output_enabled) {
@@ -662,6 +771,7 @@ static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
}
#endif
if (!frame_is_intra_only(cm)) {
#if !CONFIG_TRANSCODE
if (is_inter_block(mbmi)) {
vp9_update_mv_count(cm, xd);
@@ -670,6 +780,7 @@ static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
++cm->counts.switchable_interp[ctx][mbmi->interp_filter];
}
}
#endif
rd_opt->comp_pred_diff[SINGLE_REFERENCE] += ctx->single_pred_diff;
rd_opt->comp_pred_diff[COMPOUND_REFERENCE] += ctx->comp_pred_diff;
@@ -914,9 +1025,11 @@ static void encode_b(VP9_COMP *cpi, const TileInfo *const tile,
TOKENEXTRA **tp, int mi_row, int mi_col,
int output_enabled, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx) {
set_offsets(cpi, tile, mi_row, mi_col, bsize);
update_state(cpi, ctx, mi_row, mi_col, bsize, output_enabled);
#if CONFIG_TRANSCODE
mode_info_conversion(cpi, tile, &cpi->mb, mi_row, mi_col);
#endif
encode_superblock(cpi, tp, output_enabled, mi_row, mi_col, bsize, ctx);
if (output_enabled) {
@@ -927,6 +1040,93 @@ static void encode_b(VP9_COMP *cpi, const TileInfo *const tile,
}
}
#if CONFIG_TRANSCODE
static void encode_sb_mi(VP9_COMP *cpi, const TileInfo *const tile,
TOKENEXTRA **tp, int mi_row, int mi_col,
int output_enabled, BLOCK_SIZE bsize,
PC_TREE *pc_tree) {
VP9_COMMON *const cm = &cpi->common;
MACROBLOCK *const x = &cpi->mb;
MACROBLOCKD *const xd = &x->e_mbd;
const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
int ctx;
PARTITION_TYPE partition;
BLOCK_SIZE subsize = bsize;
int offset = mi_row * cm->mi_stride + mi_col;
MODE_INFO *mi = &cm->mi[offset];
MB_MODE_INFO *mbmi = &mi->mbmi;
set_offsets(cpi, tile, mi_row, mi_col, bsize);
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
return;
if (bsize >= BLOCK_8X8) {
ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
subsize = mbmi->sb_type; // get_subsize(bsize, pc_tree->partitioning);
} else {
ctx = 0;
subsize = BLOCK_4X4;
}
partition = partition_lookup[bsl][subsize];
if (output_enabled && bsize != BLOCK_4X4)
cm->counts.partition[ctx][partition]++;
switch (partition) {
case PARTITION_NONE:
vpx_memcpy(&(pc_tree->none.mic), mi, sizeof(MODE_INFO));
encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize,
&pc_tree->none);
break;
case PARTITION_VERT:
vpx_memcpy(&(pc_tree->vertical[0].mic), mi, sizeof(MODE_INFO));
encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize,
&pc_tree->vertical[0]);
if (mi_col + hbs < cm->mi_cols && bsize > BLOCK_8X8) {
vpx_memcpy(&(pc_tree->vertical[1].mic),
&cm->mi[offset + hbs], sizeof(MODE_INFO));
encode_b(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize,
&pc_tree->vertical[1]);
}
break;
case PARTITION_HORZ:
vpx_memcpy(&(pc_tree->horizontal[0].mic), mi, sizeof(MODE_INFO));
encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize,
&pc_tree->horizontal[0]);
if (mi_row + hbs < cm->mi_rows && bsize > BLOCK_8X8) {
vpx_memcpy(&(pc_tree->horizontal[1].mic),
&cm->mi[offset + hbs * cm->mi_stride], sizeof(MODE_INFO));
encode_b(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize,
&pc_tree->horizontal[1]);
}
break;
case PARTITION_SPLIT:
if (bsize == BLOCK_8X8) {
vpx_memcpy(&(pc_tree->leaf_split[0]->mic), mi, sizeof(MODE_INFO));
encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize,
pc_tree->leaf_split[0]);
} else {
subsize = get_subsize(bsize, PARTITION_SPLIT);
encode_sb_mi(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize,
pc_tree->split[0]);
encode_sb_mi(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize,
pc_tree->split[1]);
encode_sb_mi(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize,
pc_tree->split[2]);
encode_sb_mi(cpi, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled,
subsize, pc_tree->split[3]);
}
break;
default:
assert("Invalid partition type.");
}
if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
update_partition_context(xd, mi_row, mi_col, subsize, bsize);
}
#endif
static void encode_sb(VP9_COMP *cpi, const TileInfo *const tile,
TOKENEXTRA **tp, int mi_row, int mi_col,
int output_enabled, BLOCK_SIZE bsize,
@@ -2229,11 +2429,23 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
}
}
#if CONFIG_TRANSCODE
#define PRINT_MODE_INFO_LOAD 0
void print_mode_info(MODE_INFO *mi, int mi_row, int mi_col) {
MB_MODE_INFO *mbmi = &mi->mbmi;
fprintf(stderr, "pos (%d, %d) mode info: bsize %d, mode %d, tx size %d, ref_frame %d\n",
mi_row, mi_col, mbmi->sb_type, mbmi->mode, mbmi->tx_size,
mbmi->ref_frame[0]);
}
#endif
static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
int mi_row, TOKENEXTRA **tp) {
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
#if !CONFIG_TRANSCODE
SPEED_FEATURES *const sf = &cpi->sf;
#endif
int mi_col;
// Initialize the left context for the new SB row
@@ -2243,6 +2455,37 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
// Code each SB in the row
for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
mi_col += MI_BLOCK_SIZE) {
#if CONFIG_TRANSCODE
if (cm->frame_type == KEY_FRAME &&
!cpi->oxcf.kf_extern_coding) {
int dummy_rate;
int64_t dummy_dist;
rd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64,
&dummy_rate, &dummy_dist, 1, INT64_MAX, cpi->pc_root);
} else {
FILE *pf = cm->mi_array_pf;
assert(pf != 0);
if (pf) {
int offset = mi_row * cm->mi_stride + mi_col;
int i, j;
for (j = 0; j < MI_BLOCK_SIZE; ++j) {
for (i = 0; i < MI_BLOCK_SIZE; ++i) {
MODE_INFO *mi = &cm->mi[offset + j * cm->mi_stride + i];
fread(mi, 1, sizeof(MODE_INFO), pf);
#if PRINT_MODE_INFO_LOAD
// print out the mode_info loaded in from external file
print_mode_info(&cm->mi[offset + j * cm->mi_stride + i],
mi_row + j, mi_col + i);
#endif
}
}
}
encode_sb_mi(cpi, tile, tp, mi_row, mi_col, 1, BLOCK_64X64,
cpi->pc_root);
}
#else
int dummy_rate;
int64_t dummy_dist;
@@ -2330,6 +2573,7 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
rd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64,
&dummy_rate, &dummy_dist, 1, INT64_MAX, cpi->pc_root);
}
#endif
}
}
@@ -2967,10 +3211,14 @@ static void encode_tiles(VP9_COMP *cpi) {
vp9_tile_init(&tile, cm, tile_row, tile_col);
for (mi_row = tile.mi_row_start; mi_row < tile.mi_row_end;
mi_row += MI_BLOCK_SIZE) {
#if CONFIG_TRANSCODE
encode_rd_sb_row(cpi, &tile, mi_row, &tok);
#else
if (cpi->sf.use_nonrd_pick_mode && cm->frame_type != KEY_FRAME)
encode_nonrd_sb_row(cpi, &tile, mi_row, &tok);
else
encode_rd_sb_row(cpi, &tile, mi_row, &tok);
#endif
}
cpi->tok_count[tile_row][tile_col] = (unsigned int)(tok - old_tok);
assert(tok - cpi->tok <= get_token_alloc(cm->mb_rows, cm->mb_cols));
@@ -3001,7 +3249,11 @@ static void encode_frame_internal(VP9_COMP *cpi) {
cm->uv_dc_delta_q == 0 &&
cm->uv_ac_delta_q == 0;
#if CONFIG_TRANSCODE
cm->tx_mode = cpi->mb.e_mbd.lossless ? ONLY_4X4 : TX_MODE_SELECT;
#else
cm->tx_mode = select_tx_mode(cpi);
#endif
cpi->mb.fwd_txm4x4 = cpi->mb.e_mbd.lossless ? vp9_fwht4x4 : vp9_fdct4x4;
cpi->mb.itxm_add = cpi->mb.e_mbd.lossless ? vp9_iwht4x4_add : vp9_idct4x4_add;
@@ -3151,6 +3403,10 @@ void vp9_encode_frame(VP9_COMP *cpi) {
if (cm->interp_filter == SWITCHABLE)
cm->interp_filter = get_interp_filter(filter_thrs, is_alt_ref);
#if CONFIG_TRANSCODE
cm->reference_mode = SINGLE_REFERENCE;
cm->interp_filter = SWITCHABLE;
#endif
encode_frame_internal(cpi);
for (i = 0; i < REFERENCE_MODES; ++i)

View File

@@ -1026,6 +1026,11 @@ void vp9_remove_compressor(VP9_COMP *cpi) {
if (!cpi)
return;
#if CONFIG_TRANSCODE
if (cpi->common.mi_array_pf)
fclose(cpi->common.mi_array_pf);
#endif
if (cpi && (cpi->common.current_video_frame > 0)) {
#if CONFIG_INTERNAL_STATS

View File

@@ -238,6 +238,8 @@ typedef struct VP9EncoderConfig {
// Enable feature to reduce the frame quantization every x frames.
int frame_periodic_boost;
int kf_extern_coding;
// two pass datarate control
int two_pass_vbrbias; // two pass datarate control tweaks
int two_pass_vbrmin_section;

View File

@@ -228,12 +228,13 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
sf->last_partitioning_redo_frequency = 4;
sf->adaptive_rd_thresh = 5;
sf->use_fast_coef_costing = 0;
sf->auto_min_max_partition_size = STRICT_NEIGHBORING_MIN_MAX;
if (cm->frame_type != KEY_FRAME)
sf->auto_min_max_partition_size = STRICT_NEIGHBORING_MIN_MAX;
sf->adjust_partitioning_from_last_frame =
cm->last_frame_type != cm->frame_type || (0 ==
(frames_since_key + 1) % sf->last_partitioning_redo_frequency);
sf->subpel_force_stop = 1;
for (i = 0; i < TX_SIZES; i++) {
for (i = 0; i < TX_SIZES && cm->frame_type != KEY_FRAME; i++) {
sf->intra_y_mode_mask[i] = INTRA_DC_H_V;
sf->intra_uv_mode_mask[i] = INTRA_DC;
}

View File

@@ -38,6 +38,7 @@ struct vp9_extracfg {
unsigned int frame_parallel_decoding_mode;
AQ_MODE aq_mode;
unsigned int frame_periodic_boost;
unsigned int kf_extern_coding;
BIT_DEPTH bit_depth;
};
@@ -68,6 +69,7 @@ static const struct extraconfig_map extracfg_map[] = {
0, // frame_parallel_decoding_mode
NO_AQ, // aq_mode
0, // frame_periodic_delta_q
0, // key frame coding from external mode
BITS_8, // Bit depth
}
}
@@ -155,6 +157,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK_BOOL(extra_cfg, lossless);
RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 1);
RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
RANGE_CHECK(extra_cfg, kf_extern_coding, 0, 1);
RANGE_CHECK_HI(cfg, g_threads, 64);
RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q);
@@ -385,6 +388,8 @@ static vpx_codec_err_t set_encoder_config(
oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
oxcf->kf_extern_coding = extra_cfg->kf_extern_coding;
oxcf->ss_number_layers = cfg->ss_number_layers;
if (oxcf->ss_number_layers > 1) {
@@ -618,6 +623,13 @@ static vpx_codec_err_t ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t *ctx,
return update_extra_cfg(ctx, &extra_cfg);
}
static vpx_codec_err_t ctrl_set_kf_extern_coding(vpx_codec_alg_priv_t *ctx,
va_list args) {
struct vp9_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.kf_extern_coding = CAST(VP9E_SET_KF_EXTERN_CODING, args);
return update_extra_cfg(ctx, &extra_cfg);
}
static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
vpx_codec_priv_enc_mr_cfg_t *data) {
vpx_codec_err_t res = VPX_CODEC_OK;
@@ -679,6 +691,17 @@ static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
res = VPX_CODEC_MEM_ERROR;
else
ctx->priv->alg_priv->cpi = cpi;
#if CONFIG_TRANSCODE
if (res == VPX_CODEC_OK) {
cpi->common.mi_array_pf = fopen(ctx->config.enc->mi_fn, "rb");
if (!cpi->common.mi_array_pf) {
fprintf(stderr, "Unable to open external mode info file %s\n",
ctx->config.enc->mi_fn);
exit(0);
}
}
#endif
}
}
@@ -1223,6 +1246,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode},
{VP9E_SET_AQ_MODE, ctrl_set_aq_mode},
{VP9E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost},
{VP9E_SET_KF_EXTERN_CODING, ctrl_set_kf_extern_coding},
{VP9E_SET_SVC, ctrl_set_svc},
{VP9E_SET_SVC_PARAMETERS, ctrl_set_svc_parameters},
{VP9E_SET_SVC_LAYER_ID, ctrl_set_svc_layer_id},

View File

@@ -197,6 +197,7 @@ enum vp8e_enc_control_id {
VP9E_SET_FRAME_PARALLEL_DECODING,
VP9E_SET_AQ_MODE,
VP9E_SET_FRAME_PERIODIC_BOOST,
VP9E_SET_KF_EXTERN_CODING,
VP9E_SET_SVC,
VP9E_SET_SVC_PARAMETERS,
@@ -371,6 +372,8 @@ VPX_CTRL_USE_TYPE(VP9E_SET_AQ_MODE, unsigned int)
VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PERIODIC_BOOST, unsigned int)
VPX_CTRL_USE_TYPE(VP9E_SET_KF_EXTERN_CODING, unsigned int)
/*! @} - end defgroup vp8_encoder */
#ifdef __cplusplus
} // extern "C"

View File

@@ -275,7 +275,6 @@ extern "C" {
*/
unsigned int g_usage;
/*!\brief Maximum number of threads to use
*
* For multi-threaded implementations, use no more than this number of
@@ -667,6 +666,9 @@ extern "C" {
* ts_periodicity=8, then ts_layer_id = (0,1,0,1,0,1,0,1).
*/
unsigned int ts_layer_id[VPX_TS_MAX_PERIODICITY];
const char *mi_fn;
} vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */

View File

@@ -129,6 +129,12 @@ static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
"Debug mode (makes output deterministic)");
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
"Output filename");
#if CONFIG_TRANSCODE
static const arg_def_t mode_info_file = ARG_DEF("mi", "modeinfo", 1,
"External mode info filename");
#endif
static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
"Input file is YV12 ");
static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
@@ -369,11 +375,16 @@ static const arg_def_t frame_periodic_boost = ARG_DEF(
NULL, "frame_boost", 1,
"Enable frame periodic boost (0: off (default), 1: on)");
static const arg_def_t kf_ext_coding = ARG_DEF(
NULL, "kf-extc", 1,
"Use external coding mode for key frame coding (0: off, 1: on)");
static const arg_def_t *vp9_args[] = {
&cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
&tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
&tune_ssim, &cq_level, &max_intra_rate_pct, &lossless,
&frame_parallel_decoding, &aq_mode, &frame_periodic_boost,
&kf_ext_coding,
NULL
};
static const int vp9_arg_ctrl_map[] = {
@@ -383,7 +394,7 @@ static const int vp9_arg_ctrl_map[] = {
VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE,
VP9E_SET_FRAME_PERIODIC_BOOST,
VP9E_SET_FRAME_PERIODIC_BOOST, VP9E_SET_KF_EXTERN_CODING,
0
};
#endif
@@ -572,6 +583,9 @@ struct stream_config {
struct vpx_codec_enc_cfg cfg;
const char *out_fn;
const char *stats_fn;
#if CONFIG_TRANSCODE
const char *mi_fn;
#endif
stereo_format_t stereo_fmt;
int arg_ctrls[ARG_CTRL_CNT_MAX][2];
int arg_ctrl_cnt;
@@ -823,6 +837,9 @@ static struct stream_state *new_stream(struct VpxEncoderConfig *global,
/* Output files must be specified for each stream */
stream->config.out_fn = NULL;
#if CONFIG_TRANSCODE
stream->config.mi_fn = NULL;
#endif
stream->next = NULL;
return stream;
@@ -870,6 +887,10 @@ static int parse_stream_params(struct VpxEncoderConfig *global,
if (0) {
} else if (arg_match(&arg, &outputfile, argi)) {
config->out_fn = arg.val;
#if CONFIG_TRANSCODE
} else if (arg_match(&arg, &mode_info_file, argi)) {
config->mi_fn = arg.val;
#endif
} else if (arg_match(&arg, &fpf_name, argi)) {
config->stats_fn = arg.val;
} else if (arg_match(&arg, &use_ivf, argi)) {
@@ -1011,6 +1032,12 @@ static void validate_stream_config(const struct stream_state *stream,
fatal("Stream %d: Output file is required (specify with -o)",
streami->index);
#if CONFIG_TRANSCODE
if (!streami->config.mi_fn)
fatal("Stream %d: External mode info file is required (specify with -mi)",
streami->index);
#endif
/* Check for two streams outputting to the same file */
if (streami != stream) {
const char *a = stream->config.out_fn;
@@ -1130,11 +1157,14 @@ static void show_stream_config(struct stream_state *stream,
SHOW(kf_max_dist);
}
static void open_output_file(struct stream_state *stream,
struct VpxEncoderConfig *global) {
const char *fn = stream->config.out_fn;
const struct vpx_codec_enc_cfg *const cfg = &stream->config.cfg;
struct vpx_codec_enc_cfg *const cfg = &stream->config.cfg;
#if CONFIG_TRANSCODE
cfg->mi_fn = stream->config.mi_fn;
#endif
if (cfg->g_pass == VPX_RC_FIRST_PASS)
return;

View File

@@ -92,9 +92,11 @@ void check_encoder_config(int disable_prompt,
struct WarningListNode *warning = NULL;
struct WarningList warning_list = {0};
#if !CONFIG_TRANSCODE
check_quantizer(stream_config->rc_min_quantizer,
stream_config->rc_max_quantizer,
&warning_list);
#endif
check_lag_in_frames_realtime_deadline(stream_config->g_lag_in_frames,
global_config->deadline,
&warning_list);