Make tokenization process support recursive transform block coding
This commit makes the transform, quantization, tokenization and their corresponding inverse operations support recursive transform block coding process. Change-Id: I71f2ef3a7c2d3db7cfc63c1fd3f1337e8e0360b5
This commit is contained in:
Родитель
cffcfdb809
Коммит
52bb9dd45c
|
@ -383,6 +383,61 @@ static void predict_and_reconstruct_intra_block(MACROBLOCKD *const xd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_VAR_TX
|
||||||
|
static void decode_reconstruct_tx(MACROBLOCKD *const xd, vpx_reader *r,
|
||||||
|
MB_MODE_INFO *const mbmi,
|
||||||
|
int plane, BLOCK_SIZE plane_bsize,
|
||||||
|
int block, int blk_row, int blk_col,
|
||||||
|
TX_SIZE tx_size, int *eob_total) {
|
||||||
|
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||||
|
TX_SIZE plane_tx_size = plane ?
|
||||||
|
get_uv_tx_size_impl(mbmi->tx_size, mbmi->sb_type,
|
||||||
|
pd->subsampling_x, pd->subsampling_y) : mbmi->tx_size;
|
||||||
|
int max_blocks_high = num_4x4_blocks_high_lookup[plane_bsize];
|
||||||
|
int max_blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize];
|
||||||
|
|
||||||
|
if (xd->mb_to_bottom_edge < 0)
|
||||||
|
max_blocks_high += xd->mb_to_bottom_edge >> (5 + pd->subsampling_y);
|
||||||
|
if (xd->mb_to_right_edge < 0)
|
||||||
|
max_blocks_wide += xd->mb_to_right_edge >> (5 + pd->subsampling_x);
|
||||||
|
|
||||||
|
if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tx_size == plane_tx_size) {
|
||||||
|
PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
|
||||||
|
TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
|
||||||
|
const scan_order *sc = get_scan(tx_size, tx_type, 1);
|
||||||
|
const int eob = vp10_decode_block_tokens(xd, plane, sc,
|
||||||
|
blk_col, blk_row, tx_size,
|
||||||
|
r, mbmi->segment_id);
|
||||||
|
inverse_transform_block_inter(xd, plane, tx_size,
|
||||||
|
&pd->dst.buf[4 * blk_row * pd->dst.stride + 4 * blk_col],
|
||||||
|
pd->dst.stride, eob, block);
|
||||||
|
*eob_total += eob;
|
||||||
|
} else {
|
||||||
|
const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
|
||||||
|
int bsl = b_width_log2_lookup[bsize];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(bsl > 0);
|
||||||
|
--bsl;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
const int offsetr = blk_row + ((i >> 1) << bsl);
|
||||||
|
const int offsetc = blk_col + ((i & 0x01) << bsl);
|
||||||
|
int step = 1 << (2 * (tx_size - 1));
|
||||||
|
|
||||||
|
if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
decode_reconstruct_tx(xd, r, mbmi, plane, plane_bsize, block + i * step,
|
||||||
|
offsetr, offsetc, tx_size - 1, eob_total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int reconstruct_inter_block(MACROBLOCKD *const xd, vpx_reader *r,
|
static int reconstruct_inter_block(MACROBLOCKD *const xd, vpx_reader *r,
|
||||||
MB_MODE_INFO *const mbmi, int plane,
|
MB_MODE_INFO *const mbmi, int plane,
|
||||||
int row, int col, TX_SIZE tx_size) {
|
int row, int col, TX_SIZE tx_size) {
|
||||||
|
@ -872,13 +927,31 @@ static void decode_block(VP10Decoder *const pbi, MACROBLOCKD *const xd,
|
||||||
|
|
||||||
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
||||||
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||||
|
const int num_4x4_w = pd->n4_w;
|
||||||
|
const int num_4x4_h = pd->n4_h;
|
||||||
|
int row, col;
|
||||||
|
#if CONFIG_VAR_TX
|
||||||
|
// TODO(jingning): This can be simplified for decoder performance.
|
||||||
|
const BLOCK_SIZE plane_bsize =
|
||||||
|
get_plane_block_size(VPXMAX(bsize, BLOCK_8X8), pd);
|
||||||
|
const TX_SIZE max_tx_size = max_txsize_lookup[plane_bsize];
|
||||||
|
const int txb_size = txsize_to_bsize[max_tx_size];
|
||||||
|
int bw = num_4x4_blocks_wide_lookup[txb_size];
|
||||||
|
int block = 0;
|
||||||
|
const int step = 1 << (max_tx_size << 1);
|
||||||
|
|
||||||
|
for (row = 0; row < num_4x4_h; row += bw) {
|
||||||
|
for (col = 0; col < num_4x4_w; col += bw) {
|
||||||
|
decode_reconstruct_tx(xd, r, mbmi, plane, plane_bsize,
|
||||||
|
block, row, col, max_tx_size, &eobtotal);
|
||||||
|
block += step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
const TX_SIZE tx_size =
|
const TX_SIZE tx_size =
|
||||||
plane ? dec_get_uv_tx_size(mbmi, pd->n4_wl, pd->n4_hl)
|
plane ? dec_get_uv_tx_size(mbmi, pd->n4_wl, pd->n4_hl)
|
||||||
: mbmi->tx_size;
|
: mbmi->tx_size;
|
||||||
const int num_4x4_w = pd->n4_w;
|
|
||||||
const int num_4x4_h = pd->n4_h;
|
|
||||||
const int step = (1 << tx_size);
|
const int step = (1 << tx_size);
|
||||||
int row, col;
|
|
||||||
const int max_blocks_wide = num_4x4_w + (xd->mb_to_right_edge >= 0 ?
|
const int max_blocks_wide = num_4x4_w + (xd->mb_to_right_edge >= 0 ?
|
||||||
0 : xd->mb_to_right_edge >> (5 + pd->subsampling_x));
|
0 : xd->mb_to_right_edge >> (5 + pd->subsampling_x));
|
||||||
const int max_blocks_high = num_4x4_h + (xd->mb_to_bottom_edge >= 0 ?
|
const int max_blocks_high = num_4x4_h + (xd->mb_to_bottom_edge >= 0 ?
|
||||||
|
@ -888,6 +961,7 @@ static void decode_block(VP10Decoder *const pbi, MACROBLOCKD *const xd,
|
||||||
for (col = 0; col < max_blocks_wide; col += step)
|
for (col = 0; col < max_blocks_wide; col += step)
|
||||||
eobtotal += reconstruct_inter_block(xd, r, mbmi, plane, row, col,
|
eobtotal += reconstruct_inter_block(xd, r, mbmi, plane, row, col,
|
||||||
tx_size);
|
tx_size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!less8x8 && eobtotal == 0)
|
if (!less8x8 && eobtotal == 0)
|
||||||
|
|
|
@ -2962,7 +2962,12 @@ static void encode_superblock(VP10_COMP *cpi, ThreadData *td,
|
||||||
VPXMAX(bsize, BLOCK_8X8));
|
VPXMAX(bsize, BLOCK_8X8));
|
||||||
|
|
||||||
vp10_encode_sb(x, VPXMAX(bsize, BLOCK_8X8));
|
vp10_encode_sb(x, VPXMAX(bsize, BLOCK_8X8));
|
||||||
|
#if CONFIG_VAR_TX
|
||||||
|
vp10_tokenize_sb_inter(cpi, td, t, !output_enabled,
|
||||||
|
mi_row, mi_col, VPXMAX(bsize, BLOCK_8X8));
|
||||||
|
#else
|
||||||
vp10_tokenize_sb(cpi, td, t, !output_enabled, VPXMAX(bsize, BLOCK_8X8));
|
vp10_tokenize_sb(cpi, td, t, !output_enabled, VPXMAX(bsize, BLOCK_8X8));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_enabled) {
|
if (output_enabled) {
|
||||||
|
|
|
@ -1376,11 +1376,13 @@ static void encode_block(int plane, int block, int blk_row, int blk_col,
|
||||||
|
|
||||||
// TODO(jingning): per transformed block zero forcing only enabled for
|
// TODO(jingning): per transformed block zero forcing only enabled for
|
||||||
// luma component. will integrate chroma components as well.
|
// luma component. will integrate chroma components as well.
|
||||||
if (x->zcoeff_blk[tx_size][block] && plane == 0) {
|
// Turn this back on when the rate-distortion loop is synchronized with
|
||||||
p->eobs[block] = 0;
|
// the recursive transform block coding.
|
||||||
*a = *l = 0;
|
// if (x->zcoeff_blk[tx_size][block] && plane == 0) {
|
||||||
return;
|
// p->eobs[block] = 0;
|
||||||
}
|
// *a = *l = 0;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
if (!x->skip_recode) {
|
if (!x->skip_recode) {
|
||||||
if (x->quant_fp) {
|
if (x->quant_fp) {
|
||||||
|
@ -1488,6 +1490,57 @@ static void encode_block(int plane, int block, int blk_row, int blk_col,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_VAR_TX
|
||||||
|
static void encode_block_inter(int plane, int block, int blk_row, int blk_col,
|
||||||
|
BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
|
||||||
|
void *arg) {
|
||||||
|
struct encode_b_args *const args = arg;
|
||||||
|
MACROBLOCK *const x = args->x;
|
||||||
|
MACROBLOCKD *const xd = &x->e_mbd;
|
||||||
|
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
|
||||||
|
|
||||||
|
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||||
|
TX_SIZE plane_tx_size = plane ?
|
||||||
|
get_uv_tx_size_impl(mbmi->tx_size, mbmi->sb_type,
|
||||||
|
pd->subsampling_x, pd->subsampling_y) : mbmi->tx_size;
|
||||||
|
|
||||||
|
int max_blocks_high = num_4x4_blocks_high_lookup[plane_bsize];
|
||||||
|
int max_blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize];
|
||||||
|
|
||||||
|
if (xd->mb_to_bottom_edge < 0)
|
||||||
|
max_blocks_high += xd->mb_to_bottom_edge >> (5 + pd->subsampling_y);
|
||||||
|
if (xd->mb_to_right_edge < 0)
|
||||||
|
max_blocks_wide += xd->mb_to_right_edge >> (5 + pd->subsampling_x);
|
||||||
|
|
||||||
|
if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tx_size == plane_tx_size) {
|
||||||
|
encode_block(plane, block, blk_row, blk_col, plane_bsize,
|
||||||
|
tx_size, arg);
|
||||||
|
} else {
|
||||||
|
const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
|
||||||
|
int bsl = b_width_log2_lookup[bsize];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(bsl > 0);
|
||||||
|
--bsl;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
const int offsetr = blk_row + ((i >> 1) << bsl);
|
||||||
|
const int offsetc = blk_col + ((i & 0x01) << bsl);
|
||||||
|
int step = 1 << (2 * (tx_size - 1));
|
||||||
|
|
||||||
|
if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
encode_block_inter(plane, block + i * step, offsetr, offsetc,
|
||||||
|
plane_bsize, tx_size - 1, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
|
static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
|
||||||
BLOCK_SIZE plane_bsize,
|
BLOCK_SIZE plane_bsize,
|
||||||
TX_SIZE tx_size, void *arg) {
|
TX_SIZE tx_size, void *arg) {
|
||||||
|
@ -1541,6 +1594,19 @@ void vp10_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
||||||
|
#if CONFIG_VAR_TX
|
||||||
|
// TODO(jingning): Clean this up.
|
||||||
|
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||||
|
const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
|
||||||
|
const int mi_width = num_4x4_blocks_wide_lookup[plane_bsize];
|
||||||
|
const int mi_height = num_4x4_blocks_high_lookup[plane_bsize];
|
||||||
|
const TX_SIZE max_tx_size = max_txsize_lookup[plane_bsize];
|
||||||
|
int txb_size = txsize_to_bsize[max_tx_size];
|
||||||
|
int bh = num_4x4_blocks_wide_lookup[txb_size];
|
||||||
|
int idx, idy;
|
||||||
|
int block = 0;
|
||||||
|
int step = 1 << (max_tx_size * 2);
|
||||||
|
#endif
|
||||||
if (!x->skip_recode)
|
if (!x->skip_recode)
|
||||||
vp10_subtract_plane(x, bsize, plane);
|
vp10_subtract_plane(x, bsize, plane);
|
||||||
|
|
||||||
|
@ -1551,8 +1617,18 @@ void vp10_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize) {
|
||||||
ctx.ta[plane], ctx.tl[plane]);
|
ctx.ta[plane], ctx.tl[plane]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_VAR_TX
|
||||||
|
for (idy = 0; idy < mi_height; idy += bh) {
|
||||||
|
for (idx = 0; idx < mi_width; idx += bh) {
|
||||||
|
encode_block_inter(plane, block, idy, idx, plane_bsize,
|
||||||
|
max_tx_size, &arg);
|
||||||
|
block += step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
vp10_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
|
vp10_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block,
|
||||||
&arg);
|
&arg);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -613,6 +613,112 @@ int vp10_has_high_freq_in_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_VAR_TX
|
||||||
|
void tokenize_tx(ThreadData *td, TOKENEXTRA **t,
|
||||||
|
int dry_run, TX_SIZE tx_size, BLOCK_SIZE plane_bsize,
|
||||||
|
int blk_row, int blk_col, int block, int plane,
|
||||||
|
void *arg) {
|
||||||
|
MACROBLOCK *const x = &td->mb;
|
||||||
|
MACROBLOCKD *const xd = &x->e_mbd;
|
||||||
|
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
|
||||||
|
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||||
|
TX_SIZE plane_tx_size = plane ?
|
||||||
|
get_uv_tx_size_impl(mbmi->tx_size, mbmi->sb_type,
|
||||||
|
pd->subsampling_x, pd->subsampling_y) : mbmi->tx_size;
|
||||||
|
|
||||||
|
int max_blocks_high = num_4x4_blocks_high_lookup[plane_bsize];
|
||||||
|
int max_blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize];
|
||||||
|
if (xd->mb_to_bottom_edge < 0)
|
||||||
|
max_blocks_high += xd->mb_to_bottom_edge >> (5 + pd->subsampling_y);
|
||||||
|
if (xd->mb_to_right_edge < 0)
|
||||||
|
max_blocks_wide += xd->mb_to_right_edge >> (5 + pd->subsampling_x);
|
||||||
|
|
||||||
|
if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tx_size == plane_tx_size) {
|
||||||
|
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||||
|
BLOCK_SIZE plane_bsize = get_plane_block_size(mbmi->sb_type, pd);
|
||||||
|
if (!dry_run)
|
||||||
|
tokenize_b(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
|
||||||
|
else
|
||||||
|
set_entropy_context_b(plane, block, blk_row, blk_col,
|
||||||
|
plane_bsize, tx_size, arg);
|
||||||
|
} else {
|
||||||
|
const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
|
||||||
|
int bsl = b_width_log2_lookup[bsize];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(bsl > 0);
|
||||||
|
--bsl;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
const int offsetr = blk_row + ((i >> 1) << bsl);
|
||||||
|
const int offsetc = blk_col + ((i & 0x01) << bsl);
|
||||||
|
int step = 1 << (2 * (tx_size - 1));
|
||||||
|
|
||||||
|
if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tokenize_tx(td, t, dry_run, tx_size - 1, plane_bsize,
|
||||||
|
offsetr, offsetc, block + i * step, plane, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vp10_tokenize_sb_inter(VP10_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
|
||||||
|
int dry_run, int mi_row, int mi_col,
|
||||||
|
BLOCK_SIZE bsize) {
|
||||||
|
VP10_COMMON *const cm = &cpi->common;
|
||||||
|
MACROBLOCK *const x = &td->mb;
|
||||||
|
MACROBLOCKD *const xd = &x->e_mbd;
|
||||||
|
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
|
||||||
|
TOKENEXTRA *t_backup = *t;
|
||||||
|
const int ctx = vp10_get_skip_context(xd);
|
||||||
|
const int skip_inc = !segfeature_active(&cm->seg, mbmi->segment_id,
|
||||||
|
SEG_LVL_SKIP);
|
||||||
|
struct tokenize_b_args arg = {cpi, td, t};
|
||||||
|
int plane;
|
||||||
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mbmi->skip) {
|
||||||
|
if (!dry_run)
|
||||||
|
td->counts->skip[ctx][1] += skip_inc;
|
||||||
|
reset_skip_context(xd, bsize);
|
||||||
|
if (dry_run)
|
||||||
|
*t = t_backup;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dry_run)
|
||||||
|
td->counts->skip[ctx][0] += skip_inc;
|
||||||
|
else
|
||||||
|
*t = t_backup;
|
||||||
|
|
||||||
|
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
||||||
|
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||||
|
const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
|
||||||
|
const int mi_width = num_4x4_blocks_wide_lookup[plane_bsize];
|
||||||
|
const int mi_height = num_4x4_blocks_high_lookup[plane_bsize];
|
||||||
|
const TX_SIZE max_tx_size = max_txsize_lookup[plane_bsize];
|
||||||
|
int txb_size = txsize_to_bsize[max_tx_size];
|
||||||
|
int bh = num_4x4_blocks_wide_lookup[txb_size];
|
||||||
|
int idx, idy;
|
||||||
|
int block = 0;
|
||||||
|
int step = 1 << (max_tx_size * 2);
|
||||||
|
|
||||||
|
for (idy = 0; idy < mi_height; idy += bh) {
|
||||||
|
for (idx = 0; idx < mi_width; idx += bh) {
|
||||||
|
tokenize_tx(td, t, dry_run, max_tx_size, plane_bsize, idy, idx,
|
||||||
|
block, plane, &arg);
|
||||||
|
block += step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void vp10_tokenize_sb(VP10_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
|
void vp10_tokenize_sb(VP10_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
|
||||||
int dry_run, BLOCK_SIZE bsize) {
|
int dry_run, BLOCK_SIZE bsize) {
|
||||||
VP10_COMMON *const cm = &cpi->common;
|
VP10_COMMON *const cm = &cpi->common;
|
||||||
|
|
|
@ -51,6 +51,12 @@ int vp10_has_high_freq_in_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane);
|
||||||
struct VP10_COMP;
|
struct VP10_COMP;
|
||||||
struct ThreadData;
|
struct ThreadData;
|
||||||
|
|
||||||
|
#if CONFIG_VAR_TX
|
||||||
|
void vp10_tokenize_sb_inter(struct VP10_COMP *cpi, struct ThreadData *td,
|
||||||
|
TOKENEXTRA **t, int dry_run, int mi_row, int mi_col,
|
||||||
|
BLOCK_SIZE bsize);
|
||||||
|
#endif
|
||||||
|
|
||||||
void vp10_tokenize_sb(struct VP10_COMP *cpi, struct ThreadData *td,
|
void vp10_tokenize_sb(struct VP10_COMP *cpi, struct ThreadData *td,
|
||||||
TOKENEXTRA **t, int dry_run, BLOCK_SIZE bsize);
|
TOKENEXTRA **t, int dry_run, BLOCK_SIZE bsize);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче