📄 vp3.c
字号:
/* This table shows which types of blocks can use other blocks for * prediction. For example, INTRA is the only mode in this table to * have a frame number of 0. That means INTRA blocks can only predict * from other INTRA blocks. There are 2 golden frame coding types; * blocks encoding in these modes can only predict from other blocks * that were encoded with these 1 of these 2 modes. */ unsigned char compatible_frame[8] = { 1, /* MODE_INTER_NO_MV */ 0, /* MODE_INTRA */ 1, /* MODE_INTER_PLUS_MV */ 1, /* MODE_INTER_LAST_MV */ 1, /* MODE_INTER_PRIOR_MV */ 2, /* MODE_USING_GOLDEN */ 2, /* MODE_GOLDEN_MV */ 1 /* MODE_INTER_FOUR_MV */ }; int current_frame_type; /* there is a last DC predictor for each of the 3 frame types */ short last_dc[3]; int transform = 0; debug_vp3(" vp3: reversing DC prediction\n"); vul = vu = vur = vl = 0; last_dc[0] = last_dc[1] = last_dc[2] = 0; /* for each fragment row... */ for (y = 0; y < fragment_height; y++) { /* for each fragment in a row... */ for (x = 0; x < fragment_width; x++, i++) { /* reverse prediction if this block was coded */ if (s->all_fragments[i].coding_method != MODE_COPY) { current_frame_type = compatible_frame[s->all_fragments[i].coding_method]; debug_dc_pred(" frag %d: orig DC = %d, ", i, DC_COEFF(i)); transform= 0; if(x){ l= i-1; vl = DC_COEFF(l); if(FRAME_CODED(l) && COMPATIBLE_FRAME(l)) transform |= PL; } if(y){ u= i-fragment_width; vu = DC_COEFF(u); if(FRAME_CODED(u) && COMPATIBLE_FRAME(u)) transform |= PU; if(x){ ul= i-fragment_width-1; vul = DC_COEFF(ul); if(FRAME_CODED(ul) && COMPATIBLE_FRAME(ul)) transform |= PUL; } if(x + 1 < fragment_width){ ur= i-fragment_width+1; vur = DC_COEFF(ur); if(FRAME_CODED(ur) && COMPATIBLE_FRAME(ur)) transform |= PUR; } } debug_dc_pred("transform = %d, ", transform); if (transform == 0) { /* if there were no fragments to predict from, use last * DC saved */ predicted_dc = last_dc[current_frame_type]; debug_dc_pred("from last DC (%d) = %d\n", current_frame_type, DC_COEFF(i)); } else { /* apply the appropriate predictor transform */ predicted_dc = (predictor_transform[transform][0] * vul) + (predictor_transform[transform][1] * vu) + (predictor_transform[transform][2] * vur) + (predictor_transform[transform][3] * vl); predicted_dc /= 128; /* check for outranging on the [ul u l] and * [ul u ur l] predictors */ if ((transform == 13) || (transform == 15)) { if (FFABS(predicted_dc - vu) > 128) predicted_dc = vu; else if (FFABS(predicted_dc - vl) > 128) predicted_dc = vl; else if (FFABS(predicted_dc - vul) > 128) predicted_dc = vul; } debug_dc_pred("from pred DC = %d\n", DC_COEFF(i)); } /* at long last, apply the predictor */ if(s->coeffs[i].index){ *s->next_coeff= s->coeffs[i]; s->coeffs[i].index=0; s->coeffs[i].coeff=0; s->coeffs[i].next= s->next_coeff++; } s->coeffs[i].coeff += predicted_dc; /* save the DC */ last_dc[current_frame_type] = DC_COEFF(i); if(DC_COEFF(i) && !(s->coeff_counts[i]&127)){ s->coeff_counts[i]= 129;// s->all_fragments[i].next_coeff= s->next_coeff; s->coeffs[i].next= s->next_coeff; (s->next_coeff++)->next=NULL; } } } }}static void horizontal_filter(unsigned char *first_pixel, int stride, int *bounding_values);static void vertical_filter(unsigned char *first_pixel, int stride, int *bounding_values);/* * Perform the final rendering for a particular slice of data. * The slice number ranges from 0..(macroblock_height - 1). */static void render_slice(Vp3DecodeContext *s, int slice){ int x; int m, n; int16_t *dequantizer; DECLARE_ALIGNED_16(DCTELEM, block[64]); int motion_x = 0xdeadbeef, motion_y = 0xdeadbeef; int motion_halfpel_index; uint8_t *motion_source; int plane; int current_macroblock_entry = slice * s->macroblock_width * 6; if (slice >= s->macroblock_height) return; for (plane = 0; plane < 3; plane++) { uint8_t *output_plane = s->current_frame.data [plane]; uint8_t * last_plane = s-> last_frame.data [plane]; uint8_t *golden_plane = s-> golden_frame.data [plane]; int stride = s->current_frame.linesize[plane]; int plane_width = s->width >> !!plane; int plane_height = s->height >> !!plane; int y = slice * FRAGMENT_PIXELS << !plane ; int slice_height = y + (FRAGMENT_PIXELS << !plane); int i = s->macroblock_fragments[current_macroblock_entry + plane + 3*!!plane]; if (!s->flipped_image) stride = -stride; if(FFABS(stride) > 2048) return; //various tables are fixed size /* for each fragment row in the slice (both of them)... */ for (; y < slice_height; y += 8) { /* for each fragment in a row... */ for (x = 0; x < plane_width; x += 8, i++) { if ((i < 0) || (i >= s->fragment_count)) { av_log(s->avctx, AV_LOG_ERROR, " vp3:render_slice(): bad fragment number (%d)\n", i); return; } /* transform if this block was coded */ if ((s->all_fragments[i].coding_method != MODE_COPY) && !((s->avctx->flags & CODEC_FLAG_GRAY) && plane)) { if ((s->all_fragments[i].coding_method == MODE_USING_GOLDEN) || (s->all_fragments[i].coding_method == MODE_GOLDEN_MV)) motion_source= golden_plane; else motion_source= last_plane; motion_source += s->all_fragments[i].first_pixel; motion_halfpel_index = 0; /* sort out the motion vector if this fragment is coded * using a motion vector method */ if ((s->all_fragments[i].coding_method > MODE_INTRA) && (s->all_fragments[i].coding_method != MODE_USING_GOLDEN)) { int src_x, src_y; motion_x = s->all_fragments[i].motion_x; motion_y = s->all_fragments[i].motion_y; if(plane){ motion_x= (motion_x>>1) | (motion_x&1); motion_y= (motion_y>>1) | (motion_y&1); } src_x= (motion_x>>1) + x; src_y= (motion_y>>1) + y; if ((motion_x == 127) || (motion_y == 127)) av_log(s->avctx, AV_LOG_ERROR, " help! got invalid motion vector! (%X, %X)\n", motion_x, motion_y); motion_halfpel_index = motion_x & 0x01; motion_source += (motion_x >> 1); motion_halfpel_index |= (motion_y & 0x01) << 1; motion_source += ((motion_y >> 1) * stride); if(src_x<0 || src_y<0 || src_x + 9 >= plane_width || src_y + 9 >= plane_height){ uint8_t *temp= s->edge_emu_buffer; if(stride<0) temp -= 9*stride; else temp += 9*stride; ff_emulated_edge_mc(temp, motion_source, stride, 9, 9, src_x, src_y, plane_width, plane_height); motion_source= temp; } } /* first, take care of copying a block from either the * previous or the golden frame */ if (s->all_fragments[i].coding_method != MODE_INTRA) { /* Note, it is possible to implement all MC cases with put_no_rnd_pixels_l2 which would look more like the VP3 source but this would be slower as put_no_rnd_pixels_tab is better optimzed */ if(motion_halfpel_index != 3){ s->dsp.put_no_rnd_pixels_tab[1][motion_halfpel_index]( output_plane + s->all_fragments[i].first_pixel, motion_source, stride, 8); }else{ int d= (motion_x ^ motion_y)>>31; // d is 0 if motion_x and _y have the same sign, else -1 s->dsp.put_no_rnd_pixels_l2[1]( output_plane + s->all_fragments[i].first_pixel, motion_source - d, motion_source + stride + 1 + d, stride, 8); } dequantizer = s->qmat[1][plane]; }else{ dequantizer = s->qmat[0][plane]; } /* dequantize the DCT coefficients */ debug_idct("fragment %d, coding mode %d, DC = %d, dequant = %d:\n", i, s->all_fragments[i].coding_method, DC_COEFF(i), dequantizer[0]); if(s->avctx->idct_algo==FF_IDCT_VP3){ Coeff *coeff= s->coeffs + i; memset(block, 0, sizeof(block)); while(coeff->next){ block[coeff->index]= coeff->coeff * dequantizer[coeff->index]; coeff= coeff->next; } }else{ Coeff *coeff= s->coeffs + i; memset(block, 0, sizeof(block)); while(coeff->next){ block[coeff->index]= (coeff->coeff * dequantizer[coeff->index] + 2)>>2; coeff= coeff->next; } } /* invert DCT and place (or add) in final output */ if (s->all_fragments[i].coding_method == MODE_INTRA) { if(s->avctx->idct_algo!=FF_IDCT_VP3) block[0] += 128<<3; s->dsp.idct_put( output_plane + s->all_fragments[i].first_pixel, stride, block); } else { s->dsp.idct_add( output_plane + s->all_fragments[i].first_pixel, stride, block); } debug_idct("block after idct_%s():\n", (s->all_fragments[i].coding_method == MODE_INTRA)? "put" : "add"); for (m = 0; m < 8; m++) { for (n = 0; n < 8; n++) { debug_idct(" %3d", *(output_plane + s->all_fragments[i].first_pixel + (m * stride + n))); } debug_idct("\n"); } debug_idct("\n"); } else { /* copy directly from the previous frame */ s->dsp.put_pixels_tab[1][0]( output_plane + s->all_fragments[i].first_pixel, last_plane + s->all_fragments[i].first_pixel, stride, 8); }#if 0 /* perform the left edge filter if: * - the fragment is not on the left column * - the fragment is coded in this frame * - the fragment is not coded in this frame but the left * fragment is coded in this frame (this is done instead * of a right edge filter when rendering the left fragment * since this fragment is not available yet) */ if ((x > 0) && ((s->all_fragments[i].coding_method != MODE_COPY) || ((s->all_fragments[i].coding_method == MODE_COPY) && (s->all_fragments[i - 1].coding_method != MODE_COPY)) )) { horizontal_filter( output_plane + s->all_fragments[i].first_pixel + 7*stride, -stride, s->bounding_values_array + 127); } /* perform the top edge filter if: * - the fragment is not on the top row * - the fragment is coded in this frame * - the fragment is not coded in this frame but the above * fragment is coded in this frame (this is done instead * of a bottom edge filter when rendering the above * fragment since this fragment is not available yet) */ if ((y > 0) && ((s->all_fragments[i].coding_method != MODE_COPY) || ((s->all_fragments[i].coding_method == MODE_COPY) && (s->all_fragments[i - fragment_width].coding_method != MODE_COPY)) )) { vertical_filter( output_plane + s->all_fragments[i].first_pixel - stride, -stride, s->bounding_values_array + 127); }#end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -