📄 ebcot_encoder.c
字号:
self->master.context_buffer += self->master.row_gap + 2;
self->master.coder_state.contexts = self->master.contexts;
self->master.cpu_time = -1;
for (r=0; r < argc; r++)
if (strcmp(argv[r],"-Ccpu") == 0)
{
argv[r] = "";
self->master.cpu_time = 0;
}
self->sample_buffer_heap_mgr =
ebcot_create_sample_buffer_heap(self->master.max_dim,
self->master.row_gap);
self->code_heap_mgr = create_codeword_heap();
ebcot_initialize_global_luts();
}
/*****************************************************************************/
/* STATIC __print_usage */
/*****************************************************************************/
static void
__print_usage(encoder_ref base, FILE *dest)
{
fprintf(dest,">> EBCOT Block Encoder arguments:\n"
" -Cblk <dim> (default = 64)\n"
" -- Specify block size (dim x dim) to use in coding.\n"
" -Cheight <height> (default, same as block dimension)\n"
" -- Specifies a maximum block height; may not exceed\n"
" the block dimension, specified via `-Cblk'.\n"
" -Csub <dim> (default = 16)\n"
" -- Specify sub-block size (dim x dim) to use in coding.\n"
" -Clayers <rate> [+<layers>] [<rate> [+<layers>] [...]].\n"
" (default: 50 layers log-spaced from 0.015 to 2.0 bpp)\n"
" -- Explicitly specifies the bit-stream layer formation\n"
" parameters. <rate> is the target rate (bpp) for the\n"
" first layer (not including a final layer for the \n"
" overall target bit-rate). <layers> is the number of\n"
" extra layers which should be added for scalability.\n"
" Additional specific rate points may be specified.\n"
" -Cno_rd (default: use rate-distortion optimized truncation)\n"
" -- Turn off rate-distortion optimized block truncation\n"
" so that the generated bit-rate depends only on the\n"
" quantization step size and the maximum rate limit\n"
" is ignored. This flag may not be used in conjunction\n"
" with any form of SNR scalability.\n"
" -Ccpu -- Report CPU time for block encoding engine.\n");
}
/*****************************************************************************/
/* STATIC __push_line */
/*****************************************************************************/
static void
__push_line(encoder_ref base, ifc_int *line_buf,
int component_idx, int level_idx, int band_idx, int width)
{
the_encoder_ref self = (the_encoder_ref) base;
level_info_ptr lev;
band_info_ptr band;
line_buffering_ptr lines;
block_info_ptr info;
int n, c, blocks_wide, offset;
ifc_int *dp, *sp;
assert(component_idx < self->num_components);
lev = self->components[component_idx].levels + level_idx;
band = lev->bands + band_idx;
assert((level_idx <= self->num_levels) &&
(band_idx >= lev->min_band) && (band_idx <= lev->max_band) &&
(width == band->band_cols));
lines = &(band->lines);
blocks_wide = band->blocks_wide;
if (lines->buffers == NULL)
{ /* First call to `__push_line'. Allocate block buffers. */
lines->num_lines = 0;
lines->info = band->blocks;
lines->buffers = (ifc_int **)
local_malloc(sizeof(ifc_int *)*(size_t) blocks_wide);
for (n=0; n < blocks_wide; n++)
lines->buffers[n] =
self->sample_buffer_heap_mgr->get_buffer(
self->sample_buffer_heap_mgr);
}
/* Copy new line into all relevant block buffers. */
info = lines->info;
offset = self->master.row_gap * lines->num_lines;
for (sp=line_buf, n=0; n < blocks_wide; n++)
for (dp=lines->buffers[n]+offset, c=info[n].cols; c > 0; c--)
*(dp++) = *(sp++);
/* Advance counter and check to see if we can encode anything yet. */
lines->num_lines++;
if (lines->num_lines == info->rows)
{
for (n=0; n < blocks_wide; n++, info++)
encode_block(self,lines->buffers[n],band,info);
lines->num_lines = 0;
lines->info = info;
}
}
/*****************************************************************************/
/* STATIC __push_block */
/*****************************************************************************/
static void
__push_block(encoder_ref base, ifc_int **block_buf,
int component_idx, int level_idx, int band_idx,
int block_rows, int block_cols, int top_row, int left_col)
{
the_encoder_ref self = (the_encoder_ref) base;
level_info_ptr lev;
band_info_ptr band;
block_info_ptr block, block_pp;
int r, c, n, i, j;
int row_gap, cur_left_col, cur_block_cols, xfer_rows, xfer_cols;
ifc_int *sp, *dp, *dpp;
assert(component_idx < self->num_components);
lev = self->components[component_idx].levels + level_idx;
band = lev->bands + band_idx;
assert((level_idx <= self->num_levels) &&
(band_idx >= lev->min_band) && (band_idx <= lev->max_band) &&
(block_rows > 0) && (block_cols > 0));
if (band->push_block_rows == 0)
{ /* First call to this function for this band. */
band->push_block_rows = block_rows;
band->push_block_cols = block_cols;
for (block=band->blocks, n=0; n < band->band_blocks; n++, block++)
{
block->pushed_block_buffer = NULL;
r = 1 + ((block->rows-1)/block_rows);
c = 1 + ((block->cols-1)/block_cols);
block->unpushed_blocks = r * c;
if (n == 0)
{ /* Check that the push block dimensions are compatible. */
if (((block_rows != band->band_rows) &&
(((r * block_rows) % block->rows) != 0)) ||
((block_cols != band->band_cols) &&
(((c * block_cols) % block->cols) != 0)))
{
fprintf(stderr,"Size of blocks pushed across the "
"encoder's `push_block'\n interface function are "
"incompatible with code block dimensions!!\n"
" Either the code block dimensions must divide "
"into the\n pushed block dimensions, or vice "
"versa!\n");
exit(-1);
}
}
}
}
assert((block_rows <= band->push_block_rows) &&
(block_cols <= band->push_block_cols));
/* First, find the first relevant code block. */
block = band->blocks;
r = top_row / block->rows;
c = left_col / block->cols;
block_pp = block + r*band->blocks_wide + c;
assert((r < band->blocks_high) && (c < band->blocks_wide) &&
(top_row >= block_pp->top_row) && (left_col >= block_pp->left_col));
row_gap = self->master.row_gap;
do {
cur_left_col = left_col;
cur_block_cols = block_cols;
block = block_pp;
n = c;
do {
xfer_rows = block->rows;
xfer_cols = block->cols;
if (xfer_rows > block_rows)
xfer_rows = block_rows;
if (xfer_cols > cur_block_cols)
xfer_cols = cur_block_cols;
if (block->pushed_block_buffer == NULL)
block->pushed_block_buffer =
self->sample_buffer_heap_mgr->get_buffer(
self->sample_buffer_heap_mgr);
dpp = block->pushed_block_buffer +
row_gap*(top_row-block->top_row) + (cur_left_col-block->left_col);
for (j=0; j < xfer_rows; j++, dpp += row_gap)
for (dp=dpp, sp=block_buf[j]+(cur_left_col-left_col),
i=xfer_cols; i > 0; i--)
*(dp++) = *(sp++);
block->unpushed_blocks--;
if (block->unpushed_blocks == 0)
{
encode_block(self,block->pushed_block_buffer,band,block);
self->sample_buffer_heap_mgr->return_buffer(
self->sample_buffer_heap_mgr,
block->pushed_block_buffer);
block->pushed_block_buffer = NULL;
}
cur_block_cols -= xfer_cols;
cur_left_col += xfer_cols;
block++;
n++;
assert((cur_block_cols == 0) ||
((n < band->blocks_wide) && (cur_left_col == block->left_col)));
} while (cur_block_cols > 0);
block_buf += xfer_rows;
block_rows -= xfer_rows;
top_row += xfer_rows;
block_pp += band->blocks_wide;
r++;
assert((block_rows == 0) ||
((r < band->blocks_high) && (top_row == block_pp->top_row)));
} while (block_rows > 0);
}
/*****************************************************************************/
/* STATIC __push_tree */
/*****************************************************************************/
static void
__push_tree(encoder_ref base, ifc_int **tree_buf,
int levels, int component_idx, int root_row, int root_col)
{
the_encoder_ref self = (the_encoder_ref) base;
int lev, b, top_row, left_col, rows, cols, max_dim, r, r_off, c_off;
level_info_ptr li;
band_info_ptr band;
ifc_int **row_ptrs;
assert((component_idx < self->num_components) &&
(levels == self->num_levels));
if (self->tree_to_block_map == NULL)
self->tree_to_block_map = (ifc_int **)
local_malloc(sizeof(ifc_int *)*(size_t)(1<<self->num_levels));
row_ptrs = self->tree_to_block_map;
for (lev=0; lev < levels; lev++)
{
li = self->components[component_idx].levels + lev;
top_row = root_row << lev;
left_col = root_col << lev;
max_dim = 1<<lev;
for (b=li->min_band; b <= li->max_band; b++)
{
band = li->bands + b;
rows = band->band_rows - top_row;
cols = band->band_cols - left_col;
if (rows > max_dim)
rows = max_dim;
if (cols > max_dim)
cols = max_dim;
switch (b) {
case LL_BAND: r_off = c_off = 0; break;
case HL_BAND: r_off = 0; c_off = 1<<lev; break;
case LH_BAND: r_off = 1<<lev; c_off = 0; break;
case HH_BAND: r_off = 1<<lev; c_off = 1<<lev; break;
default: assert(0);
}
for (r=0; r < rows; r++)
row_ptrs[r] = tree_buf[r+r_off] + c_off;
__push_block(base,row_ptrs,component_idx,lev,b,
rows,cols,top_row,left_col);
}
}
}
/*****************************************************************************/
/* STATIC __terminate */
/*****************************************************************************/
static void
__terminate(encoder_ref base)
{
the_encoder_ref self = (the_encoder_ref) base;
int comp_idx, n, b;
level_info_ptr lev;
if (self->components == NULL)
{ /* Object was never initialized. */
local_free(self);
return;
}
if (self->master.cpu_time >= 0)
{
double seconds;
int rows, cols, max_rows, max_cols;
seconds = ((double)(self->master.cpu_time)) / ((double) CLOCKS_PER_SEC);
max_rows = max_cols = 0;
for (comp_idx=0; comp_idx < self->num_components; comp_idx++)
{
lev = self->components[comp_idx].levels + self->num_levels;
rows = lev->bands[0].band_rows;
cols = lev->bands[0].band_cols;
if (rows > max_rows)
max_rows = rows;
if (cols > max_cols)
max_cols = cols;
}
fprintf(stderr,
">> CPU time for EBCOT encoder:\n"
" %g seconds (%g micro-seconds per pixel)\n",
seconds,seconds*1.0E6/((double)(max_rows*max_cols)));
}
#ifdef COUNT_SYMBOLS
{
double symbol_rate;
int rows, cols, max_rows, max_cols;
max_rows = max_cols = 0;
for (comp_idx=0; comp_idx < self->num_components; comp_idx++)
{
lev = self->components[comp_idx].levels + self->num_levels;
rows = lev->bands[0].band_rows;
cols = lev->bands[0].band_cols;
if (rows > max_rows)
max_rows = rows;
if (cols > max_cols)
max_cols = cols;
}
symbol_rate =
((double) ebcot_total_symbol_count) / ((double)(max_rows*max_cols));
fprintf(stderr,
">> Symbol rate for EBCOT encoder:\n"
" %g symbols per sample\n",symbol_rate);
}
#endif
write_block_dimensions(self);
write_layer_info(self);
ebcot_send_bit_stream(self);
/* Now deallocate storage. */
for (comp_idx = 0; comp_idx < self->num_components; comp_idx++)
{
for (lev=self->components[comp_idx].levels,
n=0; n <= self->num_levels; n++, lev++)
for (b=lev->min_band; b <= lev->max_band; b++)
{
band_info_ptr band = lev->bands + b;
local_free(band->blocks->passes);
local_free(band->blocks);
if (band->lines.buffers != NULL)
{
int n;
for (n=0; n < band->blocks_wide; n++)
self->sample_buffer_heap_mgr->return_buffer(
self->sample_buffer_heap_mgr,
band->lines.buffers[n]);
local_free(band->lines.buffers);
}
}
local_free(self->components[comp_idx].levels);
}
local_free(self->components);
local_free(self->master.first_subblock);
local_free(self->master.first_quad);
self->master.context_buffer -= self->master.row_gap + 2;
local_free(self->master.context_buffer);
self->code_heap_mgr->terminate(self->code_heap_mgr);
self->sample_buffer_heap_mgr->terminate(self->sample_buffer_heap_mgr);
local_free(self->layer_info);
if (self->tree_to_block_map != NULL)
local_free(self->tree_to_block_map);
local_free(self);
}
/*****************************************************************************/
/* EXTERN create_ebcot_encoder */
/*****************************************************************************/
encoder_ref
create_ebcot_encoder(void)
{
the_encoder_ref result;
result = (the_encoder_ref)
local_malloc(sizeof(the_encoder_obj));
memset(result,0,sizeof(the_encoder_obj));
result->base.initialize = __initialize;
result->base.print_usage = __print_usage;
result->base.push_line = __push_line;
result->base.push_block = __push_block;
result->base.push_tree = __push_tree;
result->base.terminate = __terminate;
return((encoder_ref) result);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -