summaryrefslogtreecommitdiffstats
path: root/meta/recipes-multimedia/gstreamer/gst-ffmpeg-0.10.13/0001-h264-set-parameters-from-SPS-whenever-it-changes.patch
blob: 05a9de33341a79ce119fd680be07339d35aaa649 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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);