X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Frv10.c;h=29e41dc9b95c3532ba218eb90c34dd147873c3d5;hb=c242bbd8b6939507a1a6fb64101b0553d92d303f;hp=af438a34b739203df34c305cb5a28438266efeb4;hpb=fead30d4440bc7b75006ae60f2742c63a05168b3;p=ffmpeg diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index af438a34b73..29e41dc9b95 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -1,38 +1,49 @@ /* - * RV10 codec - * Copyright (c) 2000,2001 Fabrice Bellard. + * RV10/RV20 decoder + * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** - * @file rv10.c - * RV10 codec. + * @file + * RV10/RV20 decoder */ +#include "libavutil/imgutils.h" #include "avcodec.h" -#include "dsputil.h" #include "mpegvideo.h" +#include "mpeg4video.h" +#include "h263.h" //#define DEBUG +#define RV_GET_MAJOR_VER(x) ((x) >> 28) +#define RV_GET_MINOR_VER(x) (((x) >> 20) & 0xFF) +#define RV_GET_MICRO_VER(x) (((x) >> 12) & 0xFF) + #define DC_VLC_BITS 14 //FIXME find a better solution +typedef struct RVDecContext { + MpegEncContext m; + int sub_id; +} RVDecContext; + static const uint16_t rv_lum_code[256] = { 0x3e7f, 0x0f00, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05, 0x0f06, @@ -179,7 +190,7 @@ static const uint8_t rv_chrom_bits[256] = static VLC rv_dc_lum, rv_dc_chrom; -int rv_decode_dc(MpegEncContext *s, int n) +int ff_rv_decode_dc(MpegEncContext *s, int n) { int code; @@ -195,12 +206,12 @@ int rv_decode_dc(MpegEncContext *s, int n) } else if (code == 0x7d) { code = -128 + get_bits(&s->gb, 7); } else if (code == 0x7e) { - if (get_bits(&s->gb, 1) == 0) + if (get_bits1(&s->gb) == 0) code = (int8_t)(get_bits(&s->gb, 8) + 1); else code = (int8_t)(get_bits(&s->gb, 8)); } else if (code == 0x7f) { - get_bits(&s->gb, 11); + skip_bits(&s->gb, 11); code = 1; } } else { @@ -216,7 +227,7 @@ int rv_decode_dc(MpegEncContext *s, int n) } else if (code == 0x1fd) { code = -128 + get_bits(&s->gb, 7); } else if (code == 0x1fe) { - get_bits(&s->gb, 9); + skip_bits(&s->gb, 9); code = 1; } else { av_log(s->avctx, AV_LOG_ERROR, "chroma dc error\n"); @@ -229,102 +240,21 @@ int rv_decode_dc(MpegEncContext *s, int n) return -code; } -#ifdef CONFIG_ENCODERS - -/* write RV 1.0 compatible frame header */ -void rv10_encode_picture_header(MpegEncContext *s, int picture_number) -{ - int full_frame= 0; - - align_put_bits(&s->pb); - - put_bits(&s->pb, 1, 1); /* marker */ - - put_bits(&s->pb, 1, (s->pict_type == P_TYPE)); - - put_bits(&s->pb, 1, 0); /* not PB frame */ - - put_bits(&s->pb, 5, s->qscale); - - if (s->pict_type == I_TYPE) { - /* specific MPEG like DC coding not used */ - } - /* if multiple packets per frame are sent, the position at which - to display the macro blocks is coded here */ - if(!full_frame){ - put_bits(&s->pb, 6, 0); /* mb_x */ - put_bits(&s->pb, 6, 0); /* mb_y */ - put_bits(&s->pb, 12, s->mb_width * s->mb_height); - } - - put_bits(&s->pb, 3, 0); /* ignored */ -} - -void rv20_encode_picture_header(MpegEncContext *s, int picture_number){ - put_bits(&s->pb, 2, s->pict_type); //I 0 vs. 1 ? - put_bits(&s->pb, 1, 0); /* unknown bit */ - put_bits(&s->pb, 5, s->qscale); - - put_bits(&s->pb, 8, picture_number&0xFF); //FIXME wrong, but correct is not known - s->mb_x= s->mb_y= 0; - ff_h263_encode_mba(s); - - put_bits(&s->pb, 1, s->no_rounding); - - assert(s->f_code == 1); - assert(s->unrestricted_mv == 1); -// assert(s->h263_aic== (s->pict_type == I_TYPE)); - assert(s->alt_inter_vlc == 0); - assert(s->umvplus == 0); - assert(s->modified_quant==1); - assert(s->loop_filter==1); - - s->h263_aic= s->pict_type == I_TYPE; - if(s->h263_aic){ - s->y_dc_scale_table= - s->c_dc_scale_table= ff_aic_dc_scale_table; - }else{ - s->y_dc_scale_table= - s->c_dc_scale_table= ff_mpeg1_dc_scale_table; - } -} - -#if 0 /* unused, remove? */ -static int get_num(GetBitContext *gb) -{ - int n, n1; - - n = get_bits(gb, 16); - if (n >= 0x4000) { - return n - 0x4000; - } else { - n1 = get_bits(gb, 16); - return (n << 16) | n1; - } -} -#endif - -#endif //CONFIG_ENCODERS - /* read RV 1.0 compatible frame header */ static int rv10_decode_picture_header(MpegEncContext *s) { - int mb_count, pb_frame, marker, unk, mb_xy; + int mb_count, pb_frame, marker, mb_xy; -//printf("ff:%d\n", full_frame); - marker = get_bits(&s->gb, 1); + marker = get_bits1(&s->gb); - if (get_bits(&s->gb, 1)) - s->pict_type = P_TYPE; + if (get_bits1(&s->gb)) + s->pict_type = AV_PICTURE_TYPE_P; else - s->pict_type = I_TYPE; -//printf("h:%X ver:%d\n",h,s->rv10_version); + s->pict_type = AV_PICTURE_TYPE_I; if(!marker) av_log(s->avctx, AV_LOG_ERROR, "marker missing\n"); - pb_frame = get_bits(&s->gb, 1); + pb_frame = get_bits1(&s->gb); -#ifdef DEBUG - av_log(s->avctx, AV_LOG_DEBUG, "pict_type=%d pb_frame=%d\n", s->pict_type, pb_frame); -#endif + av_dlog(s->avctx, "pict_type=%d pb_frame=%d\n", s->pict_type, pb_frame); if (pb_frame){ av_log(s->avctx, AV_LOG_ERROR, "pb frame not supported\n"); @@ -337,22 +267,18 @@ static int rv10_decode_picture_header(MpegEncContext *s) return -1; } - if (s->pict_type == I_TYPE) { + if (s->pict_type == AV_PICTURE_TYPE_I) { if (s->rv10_version == 3) { /* specific MPEG like DC coding not used */ s->last_dc[0] = get_bits(&s->gb, 8); s->last_dc[1] = get_bits(&s->gb, 8); s->last_dc[2] = get_bits(&s->gb, 8); -#ifdef DEBUG - av_log(s->avctx, AV_LOG_DEBUG, "DC:%d %d %d\n", - s->last_dc[0], - s->last_dc[1], - s->last_dc[2]); -#endif + av_dlog(s->avctx, "DC:%d %d %d\n", s->last_dc[0], + s->last_dc[1], s->last_dc[2]); } } /* if multiple packets per frame are sent, the position at which - to display the macro blocks is coded here */ + to display the macroblocks is coded here */ mb_xy= s->mb_x + s->mb_y*s->mb_width; if(show_bits(&s->gb, 12)==0 || (mb_xy && mb_xy < s->mb_num)){ @@ -364,60 +290,37 @@ static int rv10_decode_picture_header(MpegEncContext *s) s->mb_y = 0; mb_count = s->mb_width * s->mb_height; } - unk= get_bits(&s->gb, 3); /* ignored */ -//printf("%d\n", unk); + skip_bits(&s->gb, 3); /* ignored */ s->f_code = 1; s->unrestricted_mv = 1; return mb_count; } -static int rv20_decode_picture_header(MpegEncContext *s) +static int rv20_decode_picture_header(RVDecContext *rv) { + MpegEncContext *s = &rv->m; int seq, mb_pos, i; - -#if 0 - GetBitContext gb= s->gb; - for(i=0; i<64; i++){ - av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&gb)); - if(i%4==3) av_log(s->avctx, AV_LOG_DEBUG, " "); - } - av_log(s->avctx, AV_LOG_DEBUG, "\n"); -#endif -#if 0 - av_log(s->avctx, AV_LOG_DEBUG, "%3dx%03d/%02Xx%02X ", s->width, s->height, s->width/4, s->height/4); - for(i=0; iavctx->extradata_size; i++){ - av_log(s->avctx, AV_LOG_DEBUG, "%02X ", ((uint8_t*)s->avctx->extradata)[i]); - if(i%4==3) av_log(s->avctx, AV_LOG_DEBUG, " "); - } - av_log(s->avctx, AV_LOG_DEBUG, "\n"); -#endif - - if(s->avctx->sub_id == 0x30202002 || s->avctx->sub_id == 0x30203002){ - if (get_bits(&s->gb, 3)){ - av_log(s->avctx, AV_LOG_ERROR, "unknown triplet set\n"); - return -1; - } - } + int rpr_bits; i= get_bits(&s->gb, 2); switch(i){ - case 0: s->pict_type= I_TYPE; break; - case 1: s->pict_type= I_TYPE; break; //hmm ... - case 2: s->pict_type= P_TYPE; break; - case 3: s->pict_type= B_TYPE; break; + case 0: s->pict_type= AV_PICTURE_TYPE_I; break; + case 1: s->pict_type= AV_PICTURE_TYPE_I; break; //hmm ... + case 2: s->pict_type= AV_PICTURE_TYPE_P; break; + case 3: s->pict_type= AV_PICTURE_TYPE_B; break; default: av_log(s->avctx, AV_LOG_ERROR, "unknown frame type\n"); return -1; } - if(s->last_picture_ptr==NULL && s->pict_type==B_TYPE){ + if(s->last_picture_ptr==NULL && s->pict_type==AV_PICTURE_TYPE_B){ av_log(s->avctx, AV_LOG_ERROR, "early B pix\n"); return -1; } - if (get_bits(&s->gb, 1)){ - av_log(s->avctx, AV_LOG_ERROR, "unknown bit set\n"); + if (get_bits1(&s->gb)){ + av_log(s->avctx, AV_LOG_ERROR, "reserved bit set\n"); return -1; } @@ -426,61 +329,54 @@ static int rv20_decode_picture_header(MpegEncContext *s) av_log(s->avctx, AV_LOG_ERROR, "error, qscale:0\n"); return -1; } - if(s->avctx->sub_id == 0x30203002){ - if (get_bits(&s->gb, 1)){ - av_log(s->avctx, AV_LOG_ERROR, "unknown bit2 set\n"); - return -1; - } - } - if(s->avctx->has_b_frames){ - int f, new_w, new_h; - int v= s->avctx->extradata_size >= 4 ? 7&((uint8_t*)s->avctx->extradata)[1] : 0; + if(RV_GET_MINOR_VER(rv->sub_id) >= 2) + s->loop_filter = get_bits1(&s->gb); - if (get_bits(&s->gb, 1)){ - av_log(s->avctx, AV_LOG_ERROR, "unknown bit3 set\n"); -// return -1; - } - seq= get_bits(&s->gb, 13)<<2; + if(RV_GET_MINOR_VER(rv->sub_id) <= 1) + seq = get_bits(&s->gb, 8) << 7; + else + seq = get_bits(&s->gb, 13) << 2; + + rpr_bits = s->avctx->extradata[1] & 7; + if(rpr_bits){ + int f, new_w, new_h; + rpr_bits = FFMIN((rpr_bits >> 1) + 1, 3); - f= get_bits(&s->gb, av_log2(v)+1); + f = get_bits(&s->gb, rpr_bits); if(f){ new_w= 4*((uint8_t*)s->avctx->extradata)[6+2*f]; new_h= 4*((uint8_t*)s->avctx->extradata)[7+2*f]; }else{ - new_w= s->width; //FIXME wrong we of course must save the original in the context - new_h= s->height; + new_w= s->orig_width ; + new_h= s->orig_height; } if(new_w != s->width || new_h != s->height){ av_log(s->avctx, AV_LOG_DEBUG, "attempting to change resolution to %dx%d\n", new_w, new_h); - MPV_common_end(s); - s->width = s->avctx->width = new_w; - s->height = s->avctx->height= new_h; - if (MPV_common_init(s) < 0) + if (av_image_check_size(new_w, new_h, 0, s->avctx) < 0) + return -1; + ff_MPV_common_end(s); + avcodec_set_dimensions(s->avctx, new_w, new_h); + s->width = new_w; + s->height = new_h; + if (ff_MPV_common_init(s) < 0) return -1; } if(s->avctx->debug & FF_DEBUG_PICT_INFO){ - av_log(s->avctx, AV_LOG_DEBUG, "F %d/%d\n", f, v); + av_log(s->avctx, AV_LOG_DEBUG, "F %d/%d\n", f, rpr_bits); } - }else{ - seq= get_bits(&s->gb, 8)*128; - } + } else if (av_image_check_size(s->width, s->height, 0, s->avctx) < 0) + return AVERROR_INVALIDDATA; + + mb_pos = ff_h263_decode_mba(s); -// if(s->avctx->sub_id <= 0x20201002){ //0x20201002 definitely needs this - mb_pos= ff_h263_decode_mba(s); -/* }else{ - mb_pos= get_bits(&s->gb, av_log2(s->mb_num-1)+1); - s->mb_x= mb_pos % s->mb_width; - s->mb_y= mb_pos / s->mb_width; - }*/ -//av_log(s->avctx, AV_LOG_DEBUG, "%d\n", seq); seq |= s->time &~0x7FFF; if(seq - s->time > 0x4000) seq -= 0x8000; if(seq - s->time < -0x4000) seq += 0x8000; if(seq != s->time){ - if(s->pict_type!=B_TYPE){ + if(s->pict_type!=AV_PICTURE_TYPE_B){ s->time= seq; s->pp_time= s->time - s->last_non_b_time; s->last_non_b_time= s->time; @@ -494,16 +390,15 @@ static int rv20_decode_picture_header(MpegEncContext *s) ff_mpeg4_init_direct_mv(s); } } -// printf("%d %d %d %d %d\n", seq, (int)s->time, (int)s->last_non_b_time, s->pp_time, s->pb_time); -/*for(i=0; i<32; i++){ - av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&s->gb)); -} -av_log(s->avctx, AV_LOG_DEBUG, "\n");*/ + s->no_rounding= get_bits1(&s->gb); + if(RV_GET_MINOR_VER(rv->sub_id) <= 1 && s->pict_type == AV_PICTURE_TYPE_B) + skip_bits(&s->gb, 5); // binary decoder reads 3+2 bits here but they don't seem to be used + s->f_code = 1; s->unrestricted_mv = 1; - s->h263_aic= s->pict_type == I_TYPE; + s->h263_aic= s->pict_type == AV_PICTURE_TYPE_I; // s->alt_inter_vlc=1; // s->obmc=1; // s->umvplus=1; @@ -515,110 +410,104 @@ av_log(s->avctx, AV_LOG_DEBUG, "\n");*/ seq, s->mb_x, s->mb_y, s->pict_type, s->qscale, s->no_rounding); } - assert(s->pict_type != B_TYPE || !s->low_delay); + assert(s->pict_type != AV_PICTURE_TYPE_B || !s->low_delay); return s->mb_width*s->mb_height - mb_pos; } -static int rv10_decode_init(AVCodecContext *avctx) +static av_cold int rv10_decode_init(AVCodecContext *avctx) { - MpegEncContext *s = avctx->priv_data; + RVDecContext *rv = avctx->priv_data; + MpegEncContext *s = &rv->m; static int done=0; + int major_ver, minor_ver, micro_ver; + + if (avctx->extradata_size < 8) { + av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n"); + return -1; + } - MPV_decode_defaults(s); + ff_MPV_decode_defaults(s); s->avctx= avctx; s->out_format = FMT_H263; s->codec_id= avctx->codec_id; + avctx->flags |= CODEC_FLAG_EMU_EDGE; - s->width = avctx->width; - s->height = avctx->height; + s->orig_width = s->width = avctx->coded_width; + s->orig_height= s->height = avctx->coded_height; s->h263_long_vectors= ((uint8_t*)avctx->extradata)[3] & 1; - avctx->sub_id= AV_RB32((uint8_t*)avctx->extradata + 4); + rv->sub_id = AV_RB32((uint8_t*)avctx->extradata + 4); - switch(avctx->sub_id){ - case 0x10000000: - s->rv10_version= 0; - s->low_delay=1; - break; - case 0x10002000: - s->rv10_version= 3; - s->low_delay=1; - s->obmc=1; - break; - case 0x10003000: - s->rv10_version= 3; - s->low_delay=1; - break; - case 0x10003001: - s->rv10_version= 3; - s->low_delay=1; - break; - case 0x20001000: /* real rv20 decoder fail on this id */ - /*case 0x20100001: - case 0x20101001: - case 0x20103001:*/ - case 0x20100000 ... 0x2019ffff: - s->low_delay=1; + major_ver = RV_GET_MAJOR_VER(rv->sub_id); + minor_ver = RV_GET_MINOR_VER(rv->sub_id); + micro_ver = RV_GET_MICRO_VER(rv->sub_id); + + s->low_delay = 1; + switch (major_ver) { + case 1: + s->rv10_version = micro_ver ? 3 : 1; + s->obmc = micro_ver == 2; break; - /*case 0x20200002: - case 0x20201002: - case 0x20203002:*/ - case 0x20200002 ... 0x202fffff: - case 0x30202002: - case 0x30203002: - s->low_delay=0; - s->avctx->has_b_frames=1; + case 2: + if (minor_ver >= 2) { + s->low_delay = 0; + s->avctx->has_b_frames = 1; + } break; default: - av_log(s->avctx, AV_LOG_ERROR, "unknown header %X\n", avctx->sub_id); + av_log(s->avctx, AV_LOG_ERROR, "unknown header %X\n", rv->sub_id); + av_log_missing_feature(avctx, "RV1/2 version", 1); + return AVERROR_PATCHWELCOME; } if(avctx->debug & FF_DEBUG_PICT_INFO){ - av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%X\n", avctx->sub_id, avctx->extradata_size >= 4 ? ((uint32_t*)avctx->extradata)[0] : -1); + av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%X\n", rv->sub_id, avctx->extradata_size >= 4 ? ((uint32_t*)avctx->extradata)[0] : -1); } - avctx->pix_fmt = PIX_FMT_YUV420P; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; - if (MPV_common_init(s) < 0) + if (ff_MPV_common_init(s) < 0) return -1; - h263_decode_init_vlc(s); + ff_h263_decode_init_vlc(); /* init rv vlc */ if (!done) { - init_vlc(&rv_dc_lum, DC_VLC_BITS, 256, + INIT_VLC_STATIC(&rv_dc_lum, DC_VLC_BITS, 256, rv_lum_bits, 1, 1, - rv_lum_code, 2, 2, 1); - init_vlc(&rv_dc_chrom, DC_VLC_BITS, 256, + rv_lum_code, 2, 2, 16384); + INIT_VLC_STATIC(&rv_dc_chrom, DC_VLC_BITS, 256, rv_chrom_bits, 1, 1, - rv_chrom_code, 2, 2, 1); + rv_chrom_code, 2, 2, 16388); done = 1; } return 0; } -static int rv10_decode_end(AVCodecContext *avctx) +static av_cold int rv10_decode_end(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; - MPV_common_end(s); + ff_MPV_common_end(s); return 0; } static int rv10_decode_packet(AVCodecContext *avctx, - uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size, int buf_size2) { - MpegEncContext *s = avctx->priv_data; - int mb_count, mb_pos, left, start_mb_x; + RVDecContext *rv = avctx->priv_data; + MpegEncContext *s = &rv->m; + int mb_count, mb_pos, left, start_mb_x, active_bits_size; - init_get_bits(&s->gb, buf, buf_size*8); - if(s->codec_id ==CODEC_ID_RV10) + active_bits_size = buf_size * 8; + init_get_bits(&s->gb, buf, FFMAX(buf_size, buf_size2) * 8); + if(s->codec_id ==AV_CODEC_ID_RV10) mb_count = rv10_decode_picture_header(s); else - mb_count = rv20_decode_picture_header(s); + mb_count = rv20_decode_picture_header(rv); if (mb_count < 0) { av_log(s->avctx, AV_LOG_ERROR, "HEADER ERROR\n"); return -1; @@ -635,25 +524,27 @@ static int rv10_decode_packet(AVCodecContext *avctx, av_log(s->avctx, AV_LOG_ERROR, "COUNT ERROR\n"); return -1; } -//if(s->pict_type == P_TYPE) return 0; if ((s->mb_x == 0 && s->mb_y == 0) || s->current_picture_ptr==NULL) { if(s->current_picture_ptr){ //FIXME write parser so we always have complete frames? - ff_er_frame_end(s); - MPV_frame_end(s); + ff_er_frame_end(&s->er); + ff_MPV_frame_end(s); s->mb_x= s->mb_y = s->resync_mb_x = s->resync_mb_y= 0; } - if(MPV_frame_start(s, avctx) < 0) + if(ff_MPV_frame_start(s, avctx) < 0) + return -1; + ff_mpeg_er_frame_start(s); + } else { + if (s->current_picture_ptr->f.pict_type != s->pict_type) { + av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n"); return -1; - ff_er_frame_start(s); + } } -#ifdef DEBUG - av_log(avctx, AV_LOG_DEBUG, "qscale=%d\n", s->qscale); -#endif + av_dlog(avctx, "qscale=%d\n", s->qscale); /* default quantization values */ - if(s->codec_id== CODEC_ID_RV10){ + if(s->codec_id== AV_CODEC_ID_RV10){ if(s->mb_y==0) s->first_slice_line=1; }else{ s->first_slice_line=1; @@ -677,7 +568,6 @@ static int rv10_decode_packet(AVCodecContext *avctx, s->rv10_first_dc_coded[0] = 0; s->rv10_first_dc_coded[1] = 0; s->rv10_first_dc_coded[2] = 0; -//printf("%d %X %X\n", s->pict_type, s->current_picture.motion_val[0], s->current_picture.motion_val[1]); s->block_wrap[0]= s->block_wrap[1]= s->block_wrap[2]= @@ -690,21 +580,38 @@ static int rv10_decode_packet(AVCodecContext *avctx, for(s->mb_num_left= mb_count; s->mb_num_left>0; s->mb_num_left--) { int ret; ff_update_block_index(s); -#ifdef DEBUG - av_log(avctx, AV_LOG_DEBUG, "**mb x=%d y=%d\n", s->mb_x, s->mb_y); -#endif + av_dlog(avctx, "**mb x=%d y=%d\n", s->mb_x, s->mb_y); s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; ret=ff_h263_decode_mb(s, s->block); - if (ret == SLICE_ERROR || s->gb.size_in_bits < get_bits_count(&s->gb)) { + // Repeat the slice end check from ff_h263_decode_mb with our active + // bitstream size + if (ret != SLICE_ERROR) { + int v = show_bits(&s->gb, 16); + + if (get_bits_count(&s->gb) + 16 > active_bits_size) + v >>= get_bits_count(&s->gb) + 16 - active_bits_size; + + if (!v) + ret = SLICE_END; + } + if (ret != SLICE_ERROR && active_bits_size < get_bits_count(&s->gb) && + 8 * buf_size2 >= get_bits_count(&s->gb)) { + active_bits_size = buf_size2 * 8; + av_log(avctx, AV_LOG_DEBUG, "update size from %d to %d\n", + 8 * buf_size, active_bits_size); + ret= SLICE_OK; + } + + if (ret == SLICE_ERROR || active_bits_size < get_bits_count(&s->gb)) { av_log(s->avctx, AV_LOG_ERROR, "ERROR at MB %d %d\n", s->mb_x, s->mb_y); return -1; } - if(s->pict_type != B_TYPE) + if(s->pict_type != AV_PICTURE_TYPE_B) ff_h263_update_motion_val(s); - MPV_decode_mb(s, s->block); + ff_MPV_decode_mb(s, s->block); if(s->loop_filter) ff_h263_loop_filter(s); @@ -718,86 +625,119 @@ static int rv10_decode_packet(AVCodecContext *avctx, if(ret == SLICE_END) break; } - ff_er_add_slice(s, start_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END); + ff_er_add_slice(&s->er, start_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_END); + + return active_bits_size; +} - return buf_size; +static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) +{ + if(avctx->slice_count) return avctx->slice_offset[n]; + else return AV_RL32(buf + n*8); } static int rv10_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - uint8_t *buf, int buf_size) + void *data, int *got_frame, + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; MpegEncContext *s = avctx->priv_data; int i; AVFrame *pict = data; + int slice_count; + const uint8_t *slices_hdr = NULL; -#ifdef DEBUG - av_log(avctx, AV_LOG_DEBUG, "*****frame %d size=%d\n", avctx->frame_number, buf_size); -#endif + av_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); /* no supplementary picture */ if (buf_size == 0) { return 0; } - if(avctx->slice_count){ - for(i=0; islice_count; i++){ - int offset= avctx->slice_offset[i]; - int size; - - if(i+1 == avctx->slice_count) - size= buf_size - offset; - else - size= avctx->slice_offset[i+1] - offset; + if(!avctx->slice_count){ + slice_count = (*buf++) + 1; + buf_size--; - rv10_decode_packet(avctx, buf+offset, size); + if (!slice_count || buf_size <= 8 * slice_count) { + av_log(avctx, AV_LOG_ERROR, "Invalid slice count: %d.\n", slice_count); + return AVERROR_INVALIDDATA; } - }else{ - rv10_decode_packet(avctx, buf, buf_size); + + slices_hdr = buf + 4; + buf += 8 * slice_count; + buf_size -= 8 * slice_count; + }else + slice_count = avctx->slice_count; + + for(i=0; i= buf_size) + return AVERROR_INVALIDDATA; + + if(i+1 == slice_count) + size= buf_size - offset; + else + size= get_slice_offset(avctx, slices_hdr, i+1) - offset; + + if(i+2 >= slice_count) + size2= buf_size - offset; + else + size2= get_slice_offset(avctx, slices_hdr, i+2) - offset; + + if (size <= 0 || size2 <= 0 || + offset + FFMAX(size, size2) > buf_size) + return AVERROR_INVALIDDATA; + + if(rv10_decode_packet(avctx, buf+offset, size, size2) > 8*size) + i++; } if(s->current_picture_ptr != NULL && s->mb_y>=s->mb_height){ - ff_er_frame_end(s); - MPV_frame_end(s); + ff_er_frame_end(&s->er); + ff_MPV_frame_end(s); - if (s->pict_type == B_TYPE || s->low_delay) { - *pict= *(AVFrame*)s->current_picture_ptr; + if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { + *pict = s->current_picture_ptr->f; } else if (s->last_picture_ptr != NULL) { - *pict= *(AVFrame*)s->last_picture_ptr; + *pict = s->last_picture_ptr->f; } if(s->last_picture_ptr || s->low_delay){ - *data_size = sizeof(AVFrame); + *got_frame = 1; ff_print_debug_info(s, pict); } - s->current_picture_ptr= NULL; //so we can detect if frame_end wasnt called (find some nicer solution...) + s->current_picture_ptr= NULL; // so we can detect if frame_end was not called (find some nicer solution...) } - return buf_size; + return avpkt->size; } -AVCodec rv10_decoder = { - "rv10", - CODEC_TYPE_VIDEO, - CODEC_ID_RV10, - sizeof(MpegEncContext), - rv10_decode_init, - NULL, - rv10_decode_end, - rv10_decode_frame, - CODEC_CAP_DR1 +AVCodec ff_rv10_decoder = { + .name = "rv10", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RV10, + .priv_data_size = sizeof(RVDecContext), + .init = rv10_decode_init, + .close = rv10_decode_end, + .decode = rv10_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), + .pix_fmts = ff_pixfmt_list_420, }; -AVCodec rv20_decoder = { - "rv20", - CODEC_TYPE_VIDEO, - CODEC_ID_RV20, - sizeof(MpegEncContext), - rv10_decode_init, - NULL, - rv10_decode_end, - rv10_decode_frame, - CODEC_CAP_DR1 | CODEC_CAP_DELAY, - .flush= ff_mpeg_flush, +AVCodec ff_rv20_decoder = { + .name = "rv20", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RV20, + .priv_data_size = sizeof(RVDecContext), + .init = rv10_decode_init, + .close = rv10_decode_end, + .decode = rv10_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush = ff_mpeg_flush, + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 2.0"), + .pix_fmts = ff_pixfmt_list_420, }; -