gst-ffmpeg: h264: set parameters from SPS whenever it changes
    
Fixes a crash in the fuzzed sample sample_varPAR.avi_s26638 with
alternating bit depths.

Upstream-Status: Backport

Signed-off-by: Yue Tao <yue.tao@windriver.com>

diff --git a/gst-libs/ext/libav/libavcodec/h264.c.old b/gst-libs/ext/libav/libavcodec/h264.c
index 3621f41..718906a 100644
--- a/gst-libs/ext/libav/libavcodec/h264.c.old
+++ b/gst-libs/ext/libav/libavcodec/h264.c
@@ -2491,6 +2491,34 @@ int ff_h264_get_profile(SPS *sps)
     return profile;
 }
 
+static int h264_set_parameter_from_sps(H264Context *h)
+{
+    MpegEncContext *s = &h->s;
+    AVCodecContext * avctx= s->avctx;
+
+    if (s->flags& CODEC_FLAG_LOW_DELAY ||
+        (h->sps.bitstream_restriction_flag && !h->sps.num_reorder_frames))
+        s->low_delay=1;
+
+    if(avctx->has_b_frames < 2)
+        avctx->has_b_frames= !s->low_delay;
+
+    if (avctx->bits_per_raw_sample != h->sps.bit_depth_luma) {
+        if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10) {
+            avctx->bits_per_raw_sample = h->sps.bit_depth_luma;
+            h->pixel_shift = h->sps.bit_depth_luma > 8;
+
+            ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma);
+            ff_h264_pred_init(&h->hpc, s->codec_id, h->sps.bit_depth_luma);
+            dsputil_init(&s->dsp, s->avctx);
+        } else {
+            av_log(avctx, AV_LOG_DEBUG, "Unsupported bit depth: %d\n", h->sps.bit_depth_luma);
+            return -1;
+        }
+    }
+    return 0;
+}
+
 /**
  * decodes a slice header.
  * This will also call MPV_common_init() and frame_start() as needed.
@@ -2505,7 +2533,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
     MpegEncContext * const s0 = &h0->s;
     unsigned int first_mb_in_slice;
     unsigned int pps_id;
-    int num_ref_idx_active_override_flag;
+    int num_ref_idx_active_override_flag, ret;
     unsigned int slice_type, tmp, i, j;
     int default_ref_list_done = 0;
     int last_pic_structure;
@@ -2569,7 +2597,17 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
         av_log(h->s.avctx, AV_LOG_ERROR, "non-existing SPS %u referenced\n", h->pps.sps_id);
         return -1;
     }
-    h->sps = *h0->sps_buffers[h->pps.sps_id];
+
+    if (h->pps.sps_id != h->current_sps_id ||
+        h0->sps_buffers[h->pps.sps_id]->new) {
+        h0->sps_buffers[h->pps.sps_id]->new = 0;
+
+        h->current_sps_id = h->pps.sps_id;
+        h->sps            = *h0->sps_buffers[h->pps.sps_id];
+
+        if ((ret = h264_set_parameter_from_sps(h)) < 0)
+            return ret;
+    }
 
     s->avctx->profile = ff_h264_get_profile(&h->sps);
     s->avctx->level   = h->sps.level_idc;
@@ -3811,26 +3811,8 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size){
         case NAL_SPS:
             init_get_bits(&s->gb, ptr, bit_length);
             ff_h264_decode_seq_parameter_set(h);
-
-            if (s->flags& CODEC_FLAG_LOW_DELAY ||
-                (h->sps.bitstream_restriction_flag && !h->sps.num_reorder_frames))
-                s->low_delay=1;
-
-            if(avctx->has_b_frames < 2)
-                avctx->has_b_frames= !s->low_delay;
-
-            if (avctx->bits_per_raw_sample != h->sps.bit_depth_luma) {
-                if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10) {
-                    avctx->bits_per_raw_sample = h->sps.bit_depth_luma;
-                    h->pixel_shift = h->sps.bit_depth_luma > 8;
-
-                    ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma);
-                    ff_h264_pred_init(&h->hpc, s->codec_id, h->sps.bit_depth_luma);
-                    dsputil_init(&s->dsp, s->avctx);
-                } else {
-                    av_log(avctx, AV_LOG_DEBUG, "Unsupported bit depth: %d\n", h->sps.bit_depth_luma);
-                    return -1;
-                }
+            if (h264_set_parameter_from_sps(h) < 0) {
+                return -1;
             }
             break;
         case NAL_PPS:
diff --git a/gst-libs/ext/libav/libavcodec/h264.h.old b/gst-libs/ext/libav/libavcodec/h264.h
index e3cc815..b77ad98 100644
--- a/gst-libs/ext/libav/libavcodec/h264.h.old
+++ b/gst-libs/ext/libav/libavcodec/h264.h
@@ -202,6 +202,7 @@ typedef struct SPS{
     int bit_depth_chroma;              ///< bit_depth_chroma_minus8 + 8
     int residual_color_transform_flag; ///< residual_colour_transform_flag
     int constraint_set_flags;          ///< constraint_set[0-3]_flag
+    int new;                              ///< flag to keep track if the decoder context needs re-init due to changed SPS
 }SPS;
 
 /**
@@ -333,6 +334,7 @@ typedef struct H264Context{
     int emu_edge_width;
     int emu_edge_height;
 
+    unsigned current_sps_id; ///< id of the current SPS
     SPS sps; ///< current sps
 
     /**
diff --git a/gst-libs/ext/libav/libavcodec/h264_ps.c.old b/gst-libs/ext/libav/libavcodec/h264_ps.c
index 7491807..0929098 100644
--- a/gst-libs/ext/libav/libavcodec/h264_ps.c.old
+++ b/gst-libs/ext/libav/libavcodec/h264_ps.c
@@ -438,10 +438,13 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){
                sps->timing_info_present_flag ? sps->time_scale : 0
                );
     }
+    sps->new = 1;
 
     av_free(h->sps_buffers[sps_id]);
-    h->sps_buffers[sps_id]= sps;
-    h->sps = *sps;
+    h->sps_buffers[sps_id] = sps;
+    h->sps                 = *sps;
+    h->current_sps_id      = sps_id;
+
     return 0;
 fail:
     av_free(sps);
