diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/vp3.c')
-rw-r--r-- | src/libffmpeg/libavcodec/vp3.c | 171 |
1 files changed, 162 insertions, 9 deletions
diff --git a/src/libffmpeg/libavcodec/vp3.c b/src/libffmpeg/libavcodec/vp3.c index 5b3f1b926..659d6913b 100644 --- a/src/libffmpeg/libavcodec/vp3.c +++ b/src/libffmpeg/libavcodec/vp3.c @@ -2093,6 +2093,9 @@ static void render_fragments(Vp3DecodeContext *s, upper_motion_limit = 7 * s->current_frame.linesize[2]; lower_motion_limit = height * s->current_frame.linesize[2] + width - 8; } + + if(ABS(stride) > 2048) + return; //various tables are fixed size /* for each fragment row... */ for (y = 0; y < height; y += 8) { @@ -2216,7 +2219,143 @@ av_log(s->avctx, AV_LOG_ERROR, " help! got beefy vector! (%X, %X)\n", motion_x, } emms_c(); +} + +#define SATURATE_U8(x) ((x) < 0) ? 0 : ((x) > 255) ? 255 : x + +static void horizontal_filter(unsigned char *first_pixel, int stride, + int *bounding_values) +{ + int i; + int filter_value; + + for (i = 0; i < 8; i++, first_pixel += stride) { + filter_value = + (first_pixel[-2] * 1) - + (first_pixel[-1] * 3) + + (first_pixel[ 0] * 3) - + (first_pixel[ 1] * 1); + filter_value = bounding_values[(filter_value + 4) >> 3]; + first_pixel[-1] = SATURATE_U8(first_pixel[-1] + filter_value); + first_pixel[ 0] = SATURATE_U8(first_pixel[ 0] - filter_value); + } +} + +static void vertical_filter(unsigned char *first_pixel, int stride, + int *bounding_values) +{ + int i; + int filter_value; + + for (i = 0; i < 8; i++, first_pixel++) { + filter_value = + (first_pixel[-(2 * stride)] * 1) - + (first_pixel[-(1 * stride)] * 3) + + (first_pixel[ (0 )] * 3) - + (first_pixel[ (1 * stride)] * 1); + filter_value = bounding_values[(filter_value + 4) >> 3]; + first_pixel[-(1 * stride)] = SATURATE_U8(first_pixel[-(1 * stride)] + filter_value); + first_pixel[0] = SATURATE_U8(first_pixel[0] - filter_value); + } +} + +static void apply_loop_filter(Vp3DecodeContext *s) +{ + int x, y, plane; + int width, height; + int fragment; + int stride; + unsigned char *plane_data; + int bounding_values[256]; + int filter_limit; + + /* find the right loop limit value */ + for (x = 63; x >= 0; x--) { + if (vp31_ac_scale_factor[x] >= s->quality_index) + break; + } + filter_limit = vp31_filter_limit_values[x]; + + /* set up the bounding values */ + memset(bounding_values, 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; + } + + for (plane = 0; plane < 3; plane++) { + + if (plane == 0) { + /* Y plane parameters */ + fragment = 0; + width = s->fragment_width; + height = s->fragment_height; + stride = s->current_frame.linesize[0]; + plane_data = s->current_frame.data[0]; + } else if (plane == 1) { + /* U plane parameters */ + fragment = s->u_fragment_start; + width = s->fragment_width / 2; + height = s->fragment_height / 2; + stride = s->current_frame.linesize[1]; + plane_data = s->current_frame.data[1]; + } else { + /* V plane parameters */ + fragment = s->v_fragment_start; + width = s->fragment_width / 2; + height = s->fragment_height / 2; + stride = s->current_frame.linesize[2]; + plane_data = s->current_frame.data[2]; + } + + for (y = 0; y < height; y++) { + + for (x = 0; x < width; x++) { + + /* do not perform left edge filter for left columns frags */ + if ((x > 0) && + (s->all_fragments[fragment].coding_method != MODE_COPY)) { + horizontal_filter( + plane_data + s->all_fragments[fragment].first_pixel, + stride, bounding_values); + } + + /* do not perform top edge filter for top row fragments */ + if ((y > 0) && + (s->all_fragments[fragment].coding_method != MODE_COPY)) { + vertical_filter( + plane_data + s->all_fragments[fragment].first_pixel, + stride, bounding_values); + } + + /* do not perform right edge filter for right column + * fragments or if right fragment neighbor is also coded + * in this frame (it will be filtered in next iteration) */ + if ((x < width - 1) && + (s->all_fragments[fragment].coding_method != MODE_COPY) && + (s->all_fragments[fragment + 1].coding_method == MODE_COPY)) { + horizontal_filter( + plane_data + s->all_fragments[fragment + 1].first_pixel, + stride, bounding_values); + } + /* do not perform bottom edge filter for bottom row + * fragments or if bottom fragment neighbor is also coded + * in this frame (it will be filtered in the next row) */ + if ((y < height - 1) && + (s->all_fragments[fragment].coding_method != MODE_COPY) && + (s->all_fragments[fragment + width].coding_method == MODE_COPY)) { + vertical_filter( + plane_data + s->all_fragments[fragment + width].first_pixel, + stride, bounding_values); + } + + fragment++; + } + } + } } /* @@ -2420,27 +2559,27 @@ static int vp3_decode_init(AVCodecContext *avctx) /* DC histograms */ init_vlc(&s->dc_vlc[i], 5, 32, &dc_bias[i][0][1], 4, 2, - &dc_bias[i][0][0], 4, 2); + &dc_bias[i][0][0], 4, 2, 0); /* group 1 AC histograms */ init_vlc(&s->ac_vlc_1[i], 5, 32, &ac_bias_0[i][0][1], 4, 2, - &ac_bias_0[i][0][0], 4, 2); + &ac_bias_0[i][0][0], 4, 2, 0); /* group 2 AC histograms */ init_vlc(&s->ac_vlc_2[i], 5, 32, &ac_bias_1[i][0][1], 4, 2, - &ac_bias_1[i][0][0], 4, 2); + &ac_bias_1[i][0][0], 4, 2, 0); /* group 3 AC histograms */ init_vlc(&s->ac_vlc_3[i], 5, 32, &ac_bias_2[i][0][1], 4, 2, - &ac_bias_2[i][0][0], 4, 2); + &ac_bias_2[i][0][0], 4, 2, 0); /* group 4 AC histograms */ init_vlc(&s->ac_vlc_4[i], 5, 32, &ac_bias_3[i][0][1], 4, 2, - &ac_bias_3[i][0][0], 4, 2); + &ac_bias_3[i][0][0], 4, 2, 0); } /* build quantization zigzag table */ @@ -2598,6 +2737,7 @@ if (!s->keyframe) { reverse_dc_prediction(s, 0, s->fragment_width, s->fragment_height); render_fragments(s, 0, s->width, s->height, 0); +// apply_loop_filter(s); if ((avctx->flags & CODEC_FLAG_GRAY) == 0) { reverse_dc_prediction(s, s->u_fragment_start, @@ -2681,6 +2821,11 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext gb) s->width = get_bits(&gb, 16) << 4; s->height = get_bits(&gb, 16) << 4; + if(avcodec_check_dimensions(avctx, s->width, s->height)){ + s->width= s->height= 0; + return -1; + } + skip_bits(&gb, 24); /* frame width */ skip_bits(&gb, 24); /* frame height */ @@ -2719,16 +2864,16 @@ static int theora_decode_comments(AVCodecContext *avctx, GetBitContext gb) { int nb_comments, i, tmp; - tmp = get_bits(&gb, 32); + tmp = get_bits_long(&gb, 32); tmp = be2me_32(tmp); while(tmp--) skip_bits(&gb, 8); - nb_comments = get_bits(&gb, 32); + nb_comments = get_bits_long(&gb, 32); nb_comments = be2me_32(nb_comments); for (i = 0; i < nb_comments; i++) { - tmp = get_bits(&gb, 32); + tmp = get_bits_long(&gb, 32); tmp = be2me_32(tmp); while(tmp--) skip_bits(&gb, 8); @@ -2774,13 +2919,20 @@ static int theora_decode_init(AVCodecContext *avctx) Vp3DecodeContext *s = avctx->priv_data; GetBitContext gb; int ptype; + uint8_t *p= avctx->extradata; + int op_bytes, i; s->theora = 1; if (!avctx->extradata_size) return -1; - init_get_bits(&gb, avctx->extradata, avctx->extradata_size); + for(i=0;i<3;i++) { + op_bytes = *(p++)<<8; + op_bytes += *(p++); + + init_get_bits(&gb, p, op_bytes); + p += op_bytes; ptype = get_bits(&gb, 8); debug_vp3("Theora headerpacket type: %x\n", ptype); @@ -2803,6 +2955,7 @@ static int theora_decode_init(AVCodecContext *avctx) theora_decode_tables(avctx, gb); break; } + } return 0; } |