Compare commits
32 Commits
v1.7.0
...
sandbox/Ji
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9d9b70a36a | ||
![]() |
1e168d12d9 | ||
![]() |
6ee6e714b4 | ||
![]() |
674cc787d3 | ||
![]() |
c765cd1a78 | ||
![]() |
9e3965ae90 | ||
![]() |
f297504f2d | ||
![]() |
b4b897605a | ||
![]() |
51959786d2 | ||
![]() |
502baedb48 | ||
![]() |
2568ff0081 | ||
![]() |
4f2aeceabe | ||
![]() |
06eed502bd | ||
![]() |
5e9f681dec | ||
![]() |
80bd67f09d | ||
![]() |
d019119777 | ||
![]() |
6af2a29764 | ||
![]() |
a3d2b5213e | ||
![]() |
0d075d907c | ||
![]() |
1bf27df775 | ||
![]() |
d7e8490d04 | ||
![]() |
68556c2f1d | ||
![]() |
19c1c1f429 | ||
![]() |
1153454cd0 | ||
![]() |
8f17deb617 | ||
![]() |
f5bb406799 | ||
![]() |
ff073a70ee | ||
![]() |
44877260a5 | ||
![]() |
06510d1ff9 | ||
![]() |
b95807f2bb | ||
![]() |
de810ac620 | ||
![]() |
0b3ffed9be |
1
configure
vendored
1
configure
vendored
@@ -271,6 +271,7 @@ EXPERIMENT_LIST="
|
||||
alpha
|
||||
multiple_arf
|
||||
spatial_svc
|
||||
transcode
|
||||
"
|
||||
CONFIG_LIST="
|
||||
external_build
|
||||
|
@@ -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) {
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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];
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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},
|
||||
|
@@ -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"
|
||||
|
@@ -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 */
|
||||
|
||||
|
||||
|
36
vpxenc.c
36
vpxenc.c
@@ -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;
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user