📄 vp3.c
字号:
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->coeff_counts[i] = 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; int decode_partial_blocks = 0; int first_c_fragment_seen; int i, j; int current_fragment; debug_vp3(" vp3: unpacking superblock coding\n"); if (s->keyframe) { debug_vp3(" keyframe-- all superblocks are fully coded\n"); memset(s->superblock_coding, SB_FULLY_CODED, s->superblock_count); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -