📄 vp3.c
字号:
* This function sets up all of the various blocks mappings:
* superblocks <-> fragments, macroblocks <-> fragments,
* superblocks <-> macroblocks
*
* Returns 0 is successful; returns 1 if *anything* went wrong.
*/
static int init_block_mapping(Vp3DecodeContext *s)
{
int i, j;
signed int hilbert_walk_mb[4];
int current_fragment = 0;
int current_width = 0;
int current_height = 0;
int right_edge = 0;
int bottom_edge = 0;
int superblock_row_inc = 0;
int *hilbert = NULL;
int mapping_index = 0;
int current_macroblock;
int c_fragment;
signed char travel_width[16] = {
1, 1, 0, -1,
0, 0, 1, 0,
1, 0, 1, 0,
0, -1, 0, 1
};
signed char travel_height[16] = {
0, 0, 1, 0,
1, 1, 0, -1,
0, 1, 0, -1,
-1, 0, -1, 0
};
signed char travel_width_mb[4] = {
1, 0, 1, 0
};
signed char travel_height_mb[4] = {
0, 1, 0, -1
};
debug_vp3(" vp3: initialize block mapping tables\n");
hilbert_walk_mb[0] = 1;
hilbert_walk_mb[1] = s->macroblock_width;
hilbert_walk_mb[2] = 1;
hilbert_walk_mb[3] = -s->macroblock_width;
/* iterate through each superblock (all planes) and map the fragments */
for (i = 0; i < s->superblock_count; i++) {
debug_init(" superblock %d (u starts @ %d, v starts @ %d)\n",
i, s->u_superblock_start, s->v_superblock_start);
/* time to re-assign the limits? */
if (i == 0) {
/* start of Y superblocks */
right_edge = s->fragment_width;
bottom_edge = s->fragment_height;
current_width = -1;
current_height = 0;
superblock_row_inc = 3 * s->fragment_width -
(s->y_superblock_width * 4 - s->fragment_width);
/* the first operation for this variable is to advance by 1 */
current_fragment = -1;
} else if (i == s->u_superblock_start) {
/* start of U superblocks */
right_edge = s->fragment_width / 2;
bottom_edge = s->fragment_height / 2;
current_width = -1;
current_height = 0;
superblock_row_inc = 3 * (s->fragment_width / 2) -
(s->c_superblock_width * 4 - s->fragment_width / 2);
/* the first operation for this variable is to advance by 1 */
current_fragment = s->fragment_start[1] - 1;
} else if (i == s->v_superblock_start) {
/* start of V superblocks */
right_edge = s->fragment_width / 2;
bottom_edge = s->fragment_height / 2;
current_width = -1;
current_height = 0;
superblock_row_inc = 3 * (s->fragment_width / 2) -
(s->c_superblock_width * 4 - s->fragment_width / 2);
/* the first operation for this variable is to advance by 1 */
current_fragment = s->fragment_start[2] - 1;
}
if (current_width >= right_edge - 1) {
/* reset width and move to next superblock row */
current_width = -1;
current_height += 4;
/* fragment is now at the start of a new superblock row */
current_fragment += superblock_row_inc;
}
/* iterate through all 16 fragments in a superblock */
for (j = 0; j < 16; j++) {
current_fragment += travel_width[j] + right_edge * travel_height[j];
current_width += travel_width[j];
current_height += travel_height[j];
/* check if the fragment is in bounds */
if ((current_width < right_edge) &&
(current_height < bottom_edge)) {
s->superblock_fragments[mapping_index] = current_fragment;
debug_init(" mapping fragment %d to superblock %d, position %d (%d/%d x %d/%d)\n",
s->superblock_fragments[mapping_index], i, j,
current_width, right_edge, current_height, bottom_edge);
} else {
s->superblock_fragments[mapping_index] = -1;
debug_init(" superblock %d, position %d has no fragment (%d/%d x %d/%d)\n",
i, j,
current_width, right_edge, current_height, bottom_edge);
}
mapping_index++;
}
}
/* initialize the superblock <-> macroblock mapping; iterate through
* all of the Y plane superblocks to build this mapping */
right_edge = s->macroblock_width;
bottom_edge = s->macroblock_height;
current_width = -1;
current_height = 0;
superblock_row_inc = s->macroblock_width -
(s->y_superblock_width * 2 - s->macroblock_width);;
hilbert = hilbert_walk_mb;
mapping_index = 0;
current_macroblock = -1;
for (i = 0; i < s->u_superblock_start; i++) {
if (current_width >= right_edge - 1) {
/* reset width and move to next superblock row */
current_width = -1;
current_height += 2;
/* macroblock is now at the start of a new superblock row */
current_macroblock += superblock_row_inc;
}
/* iterate through each potential macroblock in the superblock */
for (j = 0; j < 4; j++) {
current_macroblock += hilbert_walk_mb[j];
current_width += travel_width_mb[j];
current_height += travel_height_mb[j];
/* check if the macroblock is in bounds */
if ((current_width < right_edge) &&
(current_height < bottom_edge)) {
s->superblock_macroblocks[mapping_index] = current_macroblock;
debug_init(" mapping macroblock %d to superblock %d, position %d (%d/%d x %d/%d)\n",
s->superblock_macroblocks[mapping_index], i, j,
current_width, right_edge, current_height, bottom_edge);
} else {
s->superblock_macroblocks[mapping_index] = -1;
debug_init(" superblock %d, position %d has no macroblock (%d/%d x %d/%d)\n",
i, j,
current_width, right_edge, current_height, bottom_edge);
}
mapping_index++;
}
}
/* initialize the macroblock <-> fragment mapping */
current_fragment = 0;
current_macroblock = 0;
mapping_index = 0;
for (i = 0; i < s->fragment_height; i += 2) {
for (j = 0; j < s->fragment_width; j += 2) {
debug_init(" macroblock %d contains fragments: ", current_macroblock);
s->all_fragments[current_fragment].macroblock = current_macroblock;
s->macroblock_fragments[mapping_index++] = current_fragment;
debug_init("%d ", current_fragment);
if (j + 1 < s->fragment_width) {
s->all_fragments[current_fragment + 1].macroblock = current_macroblock;
s->macroblock_fragments[mapping_index++] = current_fragment + 1;
debug_init("%d ", current_fragment + 1);
} else
s->macroblock_fragments[mapping_index++] = -1;
if (i + 1 < s->fragment_height) {
s->all_fragments[current_fragment + s->fragment_width].macroblock =
current_macroblock;
s->macroblock_fragments[mapping_index++] =
current_fragment + s->fragment_width;
debug_init("%d ", current_fragment + s->fragment_width);
} else
s->macroblock_fragments[mapping_index++] = -1;
if ((j + 1 < s->fragment_width) && (i + 1 < s->fragment_height)) {
s->all_fragments[current_fragment + s->fragment_width + 1].macroblock =
current_macroblock;
s->macroblock_fragments[mapping_index++] =
current_fragment + s->fragment_width + 1;
debug_init("%d ", current_fragment + s->fragment_width + 1);
} else
s->macroblock_fragments[mapping_index++] = -1;
/* C planes */
c_fragment = s->fragment_start[1] +
(i * s->fragment_width / 4) + (j / 2);
s->all_fragments[c_fragment].macroblock = s->macroblock_count;
s->macroblock_fragments[mapping_index++] = c_fragment;
debug_init("%d ", c_fragment);
c_fragment = s->fragment_start[2] +
(i * s->fragment_width / 4) + (j / 2);
s->all_fragments[c_fragment].macroblock = s->macroblock_count;
s->macroblock_fragments[mapping_index++] = c_fragment;
debug_init("%d ", c_fragment);
debug_init("\n");
if (j + 2 <= s->fragment_width)
current_fragment += 2;
else
current_fragment++;
current_macroblock++;
}
current_fragment += s->fragment_width;
}
return 0; /* successful path out */
}
/*
* This function wipes out all of the fragment data.
*/
static void init_frame(Vp3DecodeContext *s, GetBitContext *gb)
{
int i;
/* zero out all of the fragment information */
s->coded_fragment_list_index = 0;
for (i = 0; i < s->fragment_count; i++) {
s->all_fragments[i].coeff_count = 0;
s->all_fragments[i].motion_x = 127;
s->all_fragments[i].motion_y = 127;
s->all_fragments[i].next_coeff= NULL;
s->coeffs[i].index=
s->coeffs[i].coeff=0;
s->coeffs[i].next= NULL;
}
}
/*
* This function sets up the dequantization tables used for a particular
* frame.
*/
static void init_dequantizer(Vp3DecodeContext *s)
{
int ac_scale_factor = s->coded_ac_scale_factor[s->quality_index];
int dc_scale_factor = s->coded_dc_scale_factor[s->quality_index];
int i, plane, inter, qri, bmi, bmj, qistart;
debug_vp3(" vp3: initializing dequantization tables\n");
for(inter=0; inter<2; inter++){
for(plane=0; plane<3; plane++){
int sum=0;
for(qri=0; qri<s->qr_count[inter][plane]; qri++){
sum+= s->qr_size[inter][plane][qri];
if(s->quality_index <= sum)
break;
}
qistart= sum - s->qr_size[inter][plane][qri];
bmi= s->qr_base[inter][plane][qri ];
bmj= s->qr_base[inter][plane][qri+1];
for(i=0; i<64; i++){
int coeff= ( 2*(sum -s->quality_index)*s->base_matrix[bmi][i]
- 2*(qistart-s->quality_index)*s->base_matrix[bmj][i]
+ s->qr_size[inter][plane][qri])
/ (2*s->qr_size[inter][plane][qri]);
int qmin= 8<<(inter + !i);
int qscale= i ? ac_scale_factor : dc_scale_factor;
s->qmat[inter][plane][i]= av_clip((qscale * coeff)/100 * 4, qmin, 4096);
}
}
}
memset(s->qscale_table, (FFMAX(s->qmat[0][0][1], s->qmat[0][1][1])+8)/16, 512); //FIXME finetune
}
/*
* This function initializes the loop filter boundary limits if the frame's
* quality index is different from the previous frame's.
*/
static void init_loop_filter(Vp3DecodeContext *s)
{
int *bounding_values= s->bounding_values_array+127;
int filter_limit;
int x;
filter_limit = s->filter_limit_values[s->quality_index];
/* set up the bounding values */
memset(s->bounding_values_array, 0, 256 * sizeof(int));
for (x = 0; x < filter_limit; x++) {
bounding_values[-x - filter_limit] = -filter_limit + x;
bounding_values[-x] = -x;
bounding_values[x] = x;
bounding_values[x + filter_limit] = filter_limit - x;
}
}
/*
* This function unpacks all of the superblock/macroblock/fragment coding
* information from the bitstream.
*/
static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
{
int bit = 0;
int current_superblock = 0;
int current_run = 0;
int decode_fully_flags = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -