rtph264depay: Warn when max SPS/PPS are collected in AVC mode.

The AVC codec_data has a flaw that it can only accomodate
31 SPS headers, even though H.264 can have 32, and 255 PPS,
when there can be 256 in H.264. When streaming RTP some
clients like to cycle through SPS/PPS ids when changing
configuration and can eventually accumulate a full set.

In that case, we have no choice but to discard one (oldest)
entry, or else the count written into the codec_data is wrong
and downstream decoding failures ensue.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/775>
This commit is contained in:
Jan Schmidt 2020-10-17 00:05:15 +11:00 committed by GStreamer Merge Bot
parent 63c7a9ae43
commit 2623404744

View file

@ -351,7 +351,7 @@ gst_rtp_h264_set_src_caps (GstRtpH264Depay * rtph264depay)
guint8 *data;
guint len;
guint new_size;
guint i;
guint i, first_sps, num_sps, first_pps, num_pps;
guchar level = 0;
guchar profile_compat = G_MAXUINT8;
@ -392,11 +392,22 @@ gst_rtp_h264_set_src_caps (GstRtpH264Depay * rtph264depay)
/* 6 bits reserved | 2 bits lengthSizeMinusOn */
*data++ = 0xff;
if (rtph264depay->sps->len > 31) {
GST_WARNING_OBJECT (rtph264depay,
"Too many SPS to put in codec_data. Sending the most recent 31");
num_sps = 31;
first_sps = rtph264depay->sps->len - 31;
} else {
num_sps = rtph264depay->sps->len;
first_sps = 0;
}
/* 3 bits reserved | 5 bits numOfSequenceParameterSets */
*data++ = 0xe0 | (rtph264depay->sps->len & 0x1f);
*data++ = 0xe0 | (num_sps & 0x1f);
/* copy all SPS */
for (i = 0; i < rtph264depay->sps->len; i++) {
for (i = first_sps; i < rtph264depay->sps->len; i++) {
gst_buffer_map (g_ptr_array_index (rtph264depay->sps, i), &nalmap,
GST_MAP_READ);
@ -409,10 +420,21 @@ gst_rtp_h264_set_src_caps (GstRtpH264Depay * rtph264depay)
gst_buffer_unmap (g_ptr_array_index (rtph264depay->sps, i), &nalmap);
}
if (rtph264depay->pps->len > 255) {
GST_WARNING_OBJECT (rtph264depay,
"Too many PPS to put in codec_data. Sending the most recent 255");
num_pps = 255;
first_pps = rtph264depay->pps->len - 255;
} else {
num_pps = rtph264depay->pps->len;
first_pps = 0;
}
/* 8 bits numOfPictureParameterSets */
*data++ = rtph264depay->pps->len;
*data++ = num_pps;
/* copy all PPS */
for (i = 0; i < rtph264depay->pps->len; i++) {
for (i = first_pps; i < rtph264depay->pps->len; i++) {
gst_buffer_map (g_ptr_array_index (rtph264depay->pps, i), &nalmap,
GST_MAP_READ);