diff options
Diffstat (limited to 'libavcodec/mpeg4videodec.c')
-rw-r--r-- | libavcodec/mpeg4videodec.c | 134 |
1 files changed, 90 insertions, 44 deletions
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 2807d50..60c0a6a 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3,23 +3,24 @@ * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2010 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/opt.h" #include "mpegvideo.h" #include "mpeg4video.h" #include "h263.h" @@ -113,7 +114,7 @@ static inline int mpeg4_is_resync(MpegEncContext *s){ int bits_count= get_bits_count(&s->gb); int v= show_bits(&s->gb, 16); - if(s->workaround_bugs&FF_BUG_NO_PADDING){ + if(s->workaround_bugs&FF_BUG_NO_PADDING && !s->resync_marker){ return 0; } @@ -130,10 +131,11 @@ static inline int mpeg4_is_resync(MpegEncContext *s){ v|= 0x7F >> (7-(bits_count&7)); if(v==0x7F) - return 1; + return s->mb_num; }else{ if(v == ff_mpeg4_resync_prefix[bits_count&7]){ - int len; + int len, mb_num; + int mb_num_bits= av_log2(s->mb_num - 1) + 1; GetBitContext gb= s->gb; skip_bits(&s->gb, 1); @@ -143,10 +145,14 @@ static inline int mpeg4_is_resync(MpegEncContext *s){ if(get_bits1(&s->gb)) break; } + mb_num= get_bits(&s->gb, mb_num_bits); + if(!mb_num || mb_num > s->mb_num || get_bits_count(&s->gb)+6 > s->gb.size_in_bits) + mb_num= -1; + s->gb= gb; if(len>=ff_mpeg4_get_video_packet_prefix_length(s)) - return 1; + return mb_num; } } return 0; @@ -373,16 +379,6 @@ int mpeg4_decode_video_packet_header(MpegEncContext *s) av_log(s->avctx, AV_LOG_ERROR, "illegal mb_num in video packet (%d %d) \n", mb_num, s->mb_num); return -1; } - if(s->pict_type == AV_PICTURE_TYPE_B){ - int mb_x = 0, mb_y = 0; - - while (s->next_picture.f.mbskip_table[s->mb_index2xy[mb_num]]) { - if (!mb_x) ff_thread_await_progress((AVFrame*)s->next_picture_ptr, mb_y++, 0); - mb_num++; - if (++mb_x == s->mb_width) mb_x = 0; - } - if(mb_num >= s->mb_num) return -1; // slice contains just skipped MBs which where already decoded - } s->mb_x= mb_num % s->mb_width; s->mb_y= mb_num / s->mb_width; @@ -990,6 +986,28 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, SKIP_COUNTER(re, &s->gb, 1+12+1); } +#if 0 + if(s->error_recognition >= FF_ER_COMPLIANT){ + const int abs_level= FFABS(level); + if(abs_level<=MAX_LEVEL && run<=MAX_RUN){ + const int run1= run - rl->max_run[last][abs_level] - 1; + if(abs_level <= rl->max_level[last][run]){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, vlc encoding possible\n"); + return -1; + } + if(s->error_recognition > FF_ER_COMPLIANT){ + if(abs_level <= rl->max_level[last][run]*2){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 1 encoding possible\n"); + return -1; + } + if(run1 >= 0 && abs_level <= rl->max_level[last][run1]){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 2 encoding possible\n"); + return -1; + } + } + } + } +#endif if (level>0) level= level * qmul + qadd; else level= level * qmul - qadd; @@ -1466,16 +1484,21 @@ end: /* per-MB end of slice check */ if(s->codec_id==CODEC_ID_MPEG4){ - if(mpeg4_is_resync(s)){ - const int delta= s->mb_x + 1 == s->mb_width ? 2 : 1; + int next= mpeg4_is_resync(s); + if(next) { + if (s->mb_x + s->mb_y*s->mb_width + 1 > next && s->avctx->error_recognition >= FF_ER_AGGRESSIVE) { + return -1; + } else if (s->mb_x + s->mb_y*s->mb_width + 1 >= next) + return SLICE_END; - if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture.f.mbskip_table[xy + delta]) { + if(s->pict_type==AV_PICTURE_TYPE_B){ + const int delta= s->mb_x + 1 == s->mb_width ? 2 : 1; ff_thread_await_progress((AVFrame*)s->next_picture_ptr, (s->mb_x + delta >= s->mb_width) ? FFMIN(s->mb_y+1, s->mb_height-1) : s->mb_y, 0); + if (s->next_picture.f.mbskip_table[xy + delta]) + return SLICE_OK; } - if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture.f.mbskip_table[xy + delta]) - return SLICE_OK; return SLICE_END; } } @@ -1486,35 +1509,36 @@ end: static int mpeg4_decode_gop_header(MpegEncContext * s, GetBitContext *gb){ int hours, minutes, seconds; - unsigned time_code = show_bits(gb, 18); - - if (time_code & 0x40) { /* marker_bit */ - hours = time_code >> 13; - minutes = time_code >> 7 & 0x3f; - seconds = time_code & 0x3f; - s->time_base = seconds + 60*(minutes + 60*hours); - skip_bits(gb, 20); /* time_code, closed_gov, broken_link */ - } else { - av_log(s->avctx, AV_LOG_WARNING, "GOP header missing marker_bit\n"); + + if(!show_bits(gb, 23)){ + av_log(s->avctx, AV_LOG_WARNING, "GOP header invalid\n"); + return -1; } + hours= get_bits(gb, 5); + minutes= get_bits(gb, 6); + skip_bits1(gb); + seconds= get_bits(gb, 6); + + s->time_base= seconds + 60*(minutes + 60*hours); + + skip_bits1(gb); + skip_bits1(gb); + return 0; } static int mpeg4_decode_profile_level(MpegEncContext * s, GetBitContext *gb){ - int profile_and_level_indication; - - profile_and_level_indication = get_bits(gb, 8); - s->avctx->profile = (profile_and_level_indication & 0xf0) >> 4; - s->avctx->level = (profile_and_level_indication & 0x0f); + s->avctx->profile = get_bits(gb, 4); + s->avctx->level = get_bits(gb, 4); - // for Simple profile, level 0 - if (s->avctx->profile == 0 && s->avctx->level == 8) { - s->avctx->level = 0; - } + // for Simple profile, level 0 + if (s->avctx->profile == 0 && s->avctx->level == 8) { + s->avctx->level = 0; + } - return 0; + return 0; } static int decode_vol_header(MpegEncContext *s, GetBitContext *gb){ @@ -2253,6 +2277,26 @@ static const AVProfile mpeg4_video_profiles[] = { { FF_PROFILE_MPEG4_ADVANCED_SIMPLE, "Advanced Simple Profile" }, }; +static const AVOption mpeg4_options[] = { + {"quarter_sample", "1/4 subpel MC", offsetof(MpegEncContext, quarter_sample), FF_OPT_TYPE_INT, {.dbl = 0}, 0, 1, 0}, + {"divx_packed", "divx style packed b frames", offsetof(MpegEncContext, divx_packed), FF_OPT_TYPE_INT, {.dbl = 0}, 0, 1, 0}, + {NULL} +}; + +static const AVClass mpeg4_class = { + "MPEG4 Video Decoder", + av_default_item_name, + mpeg4_options, + LIBAVUTIL_VERSION_INT, +}; + +static const AVClass mpeg4_vdpau_class = { + "MPEG4 Video VDPAU Decoder", + av_default_item_name, + mpeg4_options, + LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_mpeg4_decoder = { .name = "mpeg4", .type = AVMEDIA_TYPE_VIDEO, @@ -2267,7 +2311,8 @@ AVCodec ff_mpeg4_decoder = { .long_name= NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), .pix_fmts= ff_hwaccel_pixfmt_list_420, .profiles = NULL_IF_CONFIG_SMALL(mpeg4_video_profiles), - .update_thread_context= ONLY_IF_THREADS_ENABLED(ff_mpeg_update_thread_context) + .update_thread_context= ONLY_IF_THREADS_ENABLED(ff_mpeg_update_thread_context), + .priv_class = &mpeg4_class, }; @@ -2283,5 +2328,6 @@ AVCodec ff_mpeg4_vdpau_decoder = { .capabilities = CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | CODEC_CAP_HWACCEL_VDPAU, .long_name= NULL_IF_CONFIG_SMALL("MPEG-4 part 2 (VDPAU)"), .pix_fmts= (const enum PixelFormat[]){PIX_FMT_VDPAU_MPEG4, PIX_FMT_NONE}, + .priv_class = &mpeg4_vdpau_class, }; #endif |