]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/h264_ps.c
vc1: make overlap filter for I-frames bit-exact.
[ffmpeg] / libavcodec / h264_ps.c
index 423ffe8a7184c0788874c300b767605d8ff45905..44b83817d4c041abccf76253d92cbaad70839f5c 100644 (file)
@@ -2,29 +2,30 @@
  * H.26L/H.264/AVC/JVT/14496-10/... parameter set decoding
  * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
  *
- * 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 libavcodec/h264_ps.c
+ * @file
  * H.264 / AVC / MPEG4 part10 parameter set decoding.
  * @author Michael Niedermayer <michaelni@gmx.at>
  */
 
+#include "libavutil/imgutils.h"
 #include "internal.h"
 #include "dsputil.h"
 #include "avcodec.h"
@@ -176,7 +177,7 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps){
     if(sps->timing_info_present_flag){
         sps->num_units_in_tick = get_bits_long(&s->gb, 32);
         sps->time_scale = get_bits_long(&s->gb, 32);
-        if(sps->num_units_in_tick-1 > 0x7FFFFFFEU || sps->time_scale-1 > 0x7FFFFFFEU){
+        if(!sps->num_units_in_tick || !sps->time_scale){
             av_log(h->s.avctx, AV_LOG_ERROR, "time_scale/num_units_in_tick invalid or unsupported (%d/%d)\n", sps->time_scale, sps->num_units_in_tick);
             return -1;
         }
@@ -205,6 +206,12 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps){
         sps->num_reorder_frames= get_ue_golomb(&s->gb);
         get_ue_golomb(&s->gb); /*max_dec_frame_buffering*/
 
+        if(s->gb.size_in_bits < get_bits_count(&s->gb)){
+            av_log(h->s.avctx, AV_LOG_ERROR, "Overread VUI by %d bits\n", get_bits_count(&s->gb) - s->gb.size_in_bits);
+            sps->num_reorder_frames=0;
+            sps->bitstream_restriction_flag= 0;
+        }
+
         if(sps->num_reorder_frames > 16U /*max_dec_frame_buffering || max_dec_frame_buffering > 16*/){
             av_log(h->s.avctx, AV_LOG_ERROR, "illegal num_reorder_frames %d\n", sps->num_reorder_frames);
             return -1;
@@ -260,16 +267,16 @@ static void decode_scaling_matrices(H264Context *h, SPS *sps, PPS *pps, int is_s
 
 int ff_h264_decode_seq_parameter_set(H264Context *h){
     MpegEncContext * const s = &h->s;
-    int profile_idc, level_idc;
+    int profile_idc, level_idc, constraint_set_flags = 0;
     unsigned int sps_id;
     int i;
     SPS *sps;
 
     profile_idc= get_bits(&s->gb, 8);
-    get_bits1(&s->gb);   //constraint_set0_flag
-    get_bits1(&s->gb);   //constraint_set1_flag
-    get_bits1(&s->gb);   //constraint_set2_flag
-    get_bits1(&s->gb);   //constraint_set3_flag
+    constraint_set_flags |= get_bits1(&s->gb) << 0;   //constraint_set0_flag
+    constraint_set_flags |= get_bits1(&s->gb) << 1;   //constraint_set1_flag
+    constraint_set_flags |= get_bits1(&s->gb) << 2;   //constraint_set2_flag
+    constraint_set_flags |= get_bits1(&s->gb) << 3;   //constraint_set3_flag
     get_bits(&s->gb, 4); // reserved
     level_idc= get_bits(&s->gb, 8);
     sps_id= get_ue_golomb_31(&s->gb);
@@ -282,7 +289,9 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){
     if(sps == NULL)
         return -1;
 
+    sps->time_offset_length = 24;
     sps->profile_idc= profile_idc;
+    sps->constraint_set_flags = constraint_set_flags;
     sps->level_idc= level_idc;
 
     memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4));
@@ -335,7 +344,7 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){
     sps->mb_width = get_ue_golomb(&s->gb) + 1;
     sps->mb_height= get_ue_golomb(&s->gb) + 1;
     if((unsigned)sps->mb_width >= INT_MAX/16 || (unsigned)sps->mb_height >= INT_MAX/16 ||
-       avcodec_check_dimensions(NULL, 16*sps->mb_width, 16*sps->mb_height)){
+       av_image_check_size(16*sps->mb_width, 16*sps->mb_height, 0, h->s.avctx)){
         av_log(h->s.avctx, AV_LOG_ERROR, "mb_width/height overflow\n");
         goto fail;
     }
@@ -347,6 +356,10 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){
         sps->mb_aff= 0;
 
     sps->direct_8x8_inference_flag= get_bits1(&s->gb);
+    if(!sps->frame_mbs_only_flag && !sps->direct_8x8_inference_flag){
+        av_log(h->s.avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n");
+        goto fail;
+    }
 
 #ifndef ALLOW_INTERLACE
     if(sps->mb_aff)
@@ -361,7 +374,7 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){
         if(sps->crop_left || sps->crop_top){
             av_log(h->s.avctx, AV_LOG_ERROR, "insane cropping not completely supported, this could look slightly wrong ...\n");
         }
-        if(sps->crop_right >= 8 || sps->crop_bottom >= (8>> !sps->frame_mbs_only_flag)){
+        if(sps->crop_right >= 8 || sps->crop_bottom >= 8){
             av_log(h->s.avctx, AV_LOG_ERROR, "brainfart cropping not supported, this could look slightly wrong ...\n");
         }
     }else{
@@ -376,6 +389,9 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){
         if (decode_vui_parameters(h, sps) < 0)
             goto fail;
 
+    if(!sps->sar.den)
+        sps->sar.den= 1;
+
     if(s->avctx->debug&FF_DEBUG_PICT_INFO){
         av_log(h->s.avctx, AV_LOG_DEBUG, "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%d/%d/%d/%d %s %s %d/%d\n",
                sps_id, sps->profile_idc, sps->level_idc,