mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 03:00:35 +00:00
rtph264pay: Use the SPS/PPS handling function from the depayloader
Remove duplicated copies https://bugzilla.gnome.org/show_bug.cgi?id=705553
This commit is contained in:
parent
742b90747d
commit
4c6e636720
2 changed files with 47 additions and 151 deletions
|
@ -27,6 +27,9 @@
|
|||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
#include <gst/pbutils/pbutils.h>
|
||||
|
||||
/* Included to not duplicate gst_rtp_h264_add_sps_pps () */
|
||||
#include "gstrtph264depay.h"
|
||||
|
||||
#include "gstrtph264pay.h"
|
||||
|
||||
|
||||
|
@ -157,8 +160,10 @@ gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
|
|||
{
|
||||
rtph264pay->queue = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
rtph264pay->profile = 0;
|
||||
rtph264pay->sps = NULL;
|
||||
rtph264pay->pps = NULL;
|
||||
rtph264pay->sps = g_ptr_array_new_with_free_func (
|
||||
(GDestroyNotify) gst_buffer_unref);
|
||||
rtph264pay->pps = g_ptr_array_new_with_free_func (
|
||||
(GDestroyNotify) gst_buffer_unref);
|
||||
rtph264pay->last_spspps = -1;
|
||||
rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
|
||||
|
||||
|
@ -168,12 +173,8 @@ gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
|
|||
static void
|
||||
gst_rtp_h264_pay_clear_sps_pps (GstRtpH264Pay * rtph264pay)
|
||||
{
|
||||
g_list_foreach (rtph264pay->sps, (GFunc) gst_mini_object_unref, NULL);
|
||||
g_list_free (rtph264pay->sps);
|
||||
rtph264pay->sps = NULL;
|
||||
g_list_foreach (rtph264pay->pps, (GFunc) gst_mini_object_unref, NULL);
|
||||
g_list_free (rtph264pay->pps);
|
||||
rtph264pay->pps = NULL;
|
||||
g_ptr_array_set_size (rtph264pay->sps, 0);
|
||||
g_ptr_array_set_size (rtph264pay->pps, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -185,7 +186,8 @@ gst_rtp_h264_pay_finalize (GObject * object)
|
|||
|
||||
g_array_free (rtph264pay->queue, TRUE);
|
||||
|
||||
gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
|
||||
g_ptr_array_free (rtph264pay->sps, TRUE);
|
||||
g_ptr_array_free (rtph264pay->pps, TRUE);
|
||||
|
||||
g_free (rtph264pay->sprop_parameter_sets);
|
||||
|
||||
|
@ -350,18 +352,19 @@ gst_rtp_h264_pay_set_sps_pps (GstRTPBasePayload * basepayload)
|
|||
GstRtpH264Pay *payloader = GST_RTP_H264_PAY (basepayload);
|
||||
gchar *profile;
|
||||
gchar *set;
|
||||
GList *walk;
|
||||
GString *sprops;
|
||||
guint count;
|
||||
gboolean res;
|
||||
GstMapInfo map;
|
||||
guint i;
|
||||
|
||||
sprops = g_string_new ("");
|
||||
count = 0;
|
||||
|
||||
/* build the sprop-parameter-sets */
|
||||
for (walk = payloader->sps; walk; walk = g_list_next (walk)) {
|
||||
GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
|
||||
for (i = 0; i < payloader->sps->len; i++) {
|
||||
GstBuffer *sps_buf =
|
||||
GST_BUFFER_CAST (g_ptr_array_index (payloader->sps, i));
|
||||
|
||||
gst_buffer_map (sps_buf, &map, GST_MAP_READ);
|
||||
set = g_base64_encode (map.data, map.size);
|
||||
|
@ -371,8 +374,9 @@ gst_rtp_h264_pay_set_sps_pps (GstRTPBasePayload * basepayload)
|
|||
g_free (set);
|
||||
count++;
|
||||
}
|
||||
for (walk = payloader->pps; walk; walk = g_list_next (walk)) {
|
||||
GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
|
||||
for (i = 0; i < payloader->pps->len; i++) {
|
||||
GstBuffer *pps_buf =
|
||||
GST_BUFFER_CAST (g_ptr_array_index (payloader->pps, i));
|
||||
|
||||
gst_buffer_map (pps_buf, &map, GST_MAP_READ);
|
||||
set = g_base64_encode (map.data, map.size);
|
||||
|
@ -398,29 +402,6 @@ gst_rtp_h264_pay_set_sps_pps (GstRTPBasePayload * basepayload)
|
|||
return res;
|
||||
}
|
||||
|
||||
static GList *
|
||||
add_sps_pps_without_duplicates (GList * list, GstBuffer * buffer)
|
||||
{
|
||||
GList *walk;
|
||||
GstMapInfo map;
|
||||
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
|
||||
for (walk = list; walk; walk = walk->next) {
|
||||
if (gst_buffer_get_size (walk->data) == map.size &&
|
||||
!gst_buffer_memcmp (walk->data, 0, map.data, map.size)) {
|
||||
/* Same data */
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
gst_buffer_unref (buffer);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
list = g_list_append (list, buffer);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
|
||||
|
@ -517,9 +498,8 @@ gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
|
|||
/* make a buffer out of it and add to SPS list */
|
||||
sps_buf = gst_buffer_new_and_alloc (nal_size);
|
||||
gst_buffer_fill (sps_buf, 0, data, nal_size);
|
||||
rtph264pay->sps = add_sps_pps_without_duplicates (rtph264pay->sps,
|
||||
sps_buf);
|
||||
|
||||
gst_rtp_h264_add_sps_pps (GST_ELEMENT (rtph264pay), rtph264pay->sps,
|
||||
rtph264pay->pps, sps_buf);
|
||||
data += nal_size;
|
||||
size -= nal_size;
|
||||
}
|
||||
|
@ -550,8 +530,8 @@ gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
|
|||
/* make a buffer out of it and add to PPS list */
|
||||
pps_buf = gst_buffer_new_and_alloc (nal_size);
|
||||
gst_buffer_fill (pps_buf, 0, data, nal_size);
|
||||
rtph264pay->pps = add_sps_pps_without_duplicates (rtph264pay->pps,
|
||||
pps_buf);
|
||||
gst_rtp_h264_add_sps_pps (GST_ELEMENT (rtph264pay), rtph264pay->sps,
|
||||
rtph264pay->pps, pps_buf);
|
||||
|
||||
data += nal_size;
|
||||
size -= nal_size;
|
||||
|
@ -600,7 +580,7 @@ gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
|
|||
{
|
||||
const gchar *ps;
|
||||
gchar **params;
|
||||
guint len, num_sps, num_pps;
|
||||
guint len;
|
||||
gint i;
|
||||
GstBuffer *buf;
|
||||
|
||||
|
@ -615,15 +595,12 @@ gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
|
|||
|
||||
GST_DEBUG_OBJECT (rtph264pay, "we have %d params", len);
|
||||
|
||||
num_sps = num_pps = 0;
|
||||
|
||||
for (i = 0; params[i]; i++) {
|
||||
gsize nal_len;
|
||||
GstMapInfo map;
|
||||
guint8 *nalp;
|
||||
guint save = 0;
|
||||
gint state = 0;
|
||||
guint8 nal_type;
|
||||
|
||||
nal_len = strlen (params[i]);
|
||||
buf = gst_buffer_new_and_alloc (nal_len);
|
||||
|
@ -631,7 +608,6 @@ gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
|
|||
gst_buffer_map (buf, &map, GST_MAP_WRITE);
|
||||
nalp = map.data;
|
||||
nal_len = g_base64_decode_step (params[i], nal_len, nalp, &state, &save);
|
||||
nal_type = nalp[0];
|
||||
gst_buffer_unmap (buf, &map);
|
||||
gst_buffer_resize (buf, 0, nal_len);
|
||||
|
||||
|
@ -640,16 +616,8 @@ gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* append to the right list */
|
||||
if ((nal_type & 0x1f) == 7) {
|
||||
GST_DEBUG_OBJECT (rtph264pay, "adding param %d as SPS %d", i, num_sps);
|
||||
rtph264pay->sps = add_sps_pps_without_duplicates (rtph264pay->sps, buf);
|
||||
num_sps++;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (rtph264pay, "adding param %d as PPS %d", i, num_pps);
|
||||
rtph264pay->pps = add_sps_pps_without_duplicates (rtph264pay->pps, buf);
|
||||
num_pps++;
|
||||
}
|
||||
gst_rtp_h264_add_sps_pps (GST_ELEMENT (rtph264pay), rtph264pay->sps,
|
||||
rtph264pay->pps, buf);
|
||||
}
|
||||
g_strfreev (params);
|
||||
}
|
||||
|
@ -697,10 +665,7 @@ static gboolean
|
|||
gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
|
||||
const guint8 * data, guint size, GstClockTime dts, GstClockTime pts)
|
||||
{
|
||||
const guint8 *sps = NULL, *pps = NULL;
|
||||
guint sps_len = 0, pps_len = 0;
|
||||
guint8 header, type;
|
||||
guint len;
|
||||
gboolean updated;
|
||||
|
||||
/* default is no update */
|
||||
|
@ -708,103 +673,32 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
|
|||
|
||||
GST_DEBUG ("NAL payload len=%u", size);
|
||||
|
||||
len = size;
|
||||
header = data[0];
|
||||
type = header & 0x1f;
|
||||
|
||||
/* keep sps & pps separately so that we can update either one
|
||||
* independently. We also record the timestamp of the last SPS/PPS so
|
||||
/* We record the timestamp of the last SPS/PPS so
|
||||
* that we can insert them at regular intervals and when needed. */
|
||||
if (SPS_TYPE_ID == type) {
|
||||
if (SPS_TYPE_ID == type || PPS_TYPE_ID == type) {
|
||||
GstBuffer *nal;
|
||||
|
||||
/* encode the entire SPS NAL in base64 */
|
||||
GST_DEBUG ("Found SPS %x %x %x Len=%u", (header >> 7),
|
||||
(header >> 5) & 3, type, len);
|
||||
GST_DEBUG ("Found %s %x %x %x Len=%u", type == SPS_TYPE_ID ? "SPS" : "PPS",
|
||||
(header >> 7), (header >> 5) & 3, type, size);
|
||||
|
||||
nal = gst_buffer_new_allocate (NULL, size, NULL);
|
||||
gst_buffer_fill (nal, 0, data, size);
|
||||
|
||||
updated = gst_rtp_h264_add_sps_pps (GST_ELEMENT (payloader),
|
||||
payloader->sps, payloader->pps, nal);
|
||||
|
||||
sps = data;
|
||||
sps_len = len;
|
||||
/* remember when we last saw SPS */
|
||||
if (pts != -1)
|
||||
payloader->last_spspps = pts;
|
||||
} else if (PPS_TYPE_ID == type) {
|
||||
/* encoder the entire PPS NAL in base64 */
|
||||
GST_DEBUG ("Found PPS %x %x %x Len = %u",
|
||||
(header >> 7), (header >> 5) & 3, type, len);
|
||||
|
||||
pps = data;
|
||||
pps_len = len;
|
||||
/* remember when we last saw PPS */
|
||||
if (pts != -1)
|
||||
if (updated && pts != -1)
|
||||
payloader->last_spspps = pts;
|
||||
} else {
|
||||
GST_DEBUG ("NAL: %x %x %x Len = %u", (header >> 7),
|
||||
(header >> 5) & 3, type, len);
|
||||
(header >> 5) & 3, type, size);
|
||||
}
|
||||
|
||||
/* If we encountered an SPS and/or a PPS, check if it's the
|
||||
* same as the one we have. If not, update our version and
|
||||
* set updated to TRUE
|
||||
*/
|
||||
if (sps_len > 0) {
|
||||
GstBuffer *sps_buf;
|
||||
|
||||
if (payloader->sps != NULL) {
|
||||
sps_buf = GST_BUFFER_CAST (payloader->sps->data);
|
||||
|
||||
if (gst_buffer_memcmp (sps_buf, 0, sps, sps_len)) {
|
||||
/* something changed, update */
|
||||
payloader->profile = (sps[1] << 16) + (sps[2] << 8) + sps[3];
|
||||
GST_DEBUG ("Profile level IDC = %06x", payloader->profile);
|
||||
updated = TRUE;
|
||||
}
|
||||
} else {
|
||||
/* no previous SPS, update */
|
||||
updated = TRUE;
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
sps_buf = gst_buffer_new_and_alloc (sps_len);
|
||||
gst_buffer_fill (sps_buf, 0, sps, sps_len);
|
||||
|
||||
if (payloader->sps) {
|
||||
/* replace old buffer */
|
||||
gst_buffer_unref (payloader->sps->data);
|
||||
payloader->sps->data = sps_buf;
|
||||
} else {
|
||||
/* add new buffer */
|
||||
payloader->sps = g_list_prepend (payloader->sps, sps_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pps_len > 0) {
|
||||
GstBuffer *pps_buf;
|
||||
|
||||
if (payloader->pps != NULL) {
|
||||
pps_buf = GST_BUFFER_CAST (payloader->pps->data);
|
||||
|
||||
if (gst_buffer_memcmp (pps_buf, 0, pps, pps_len)) {
|
||||
/* something changed, update */
|
||||
updated = TRUE;
|
||||
}
|
||||
} else {
|
||||
/* no previous SPS, update */
|
||||
updated = TRUE;
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
pps_buf = gst_buffer_new_and_alloc (pps_len);
|
||||
gst_buffer_fill (pps_buf, 0, pps, pps_len);
|
||||
|
||||
if (payloader->pps) {
|
||||
/* replace old buffer */
|
||||
gst_buffer_unref (payloader->pps->data);
|
||||
payloader->pps->data = pps_buf;
|
||||
} else {
|
||||
/* add new buffer */
|
||||
payloader->pps = g_list_prepend (payloader->pps, pps_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
|
@ -817,10 +711,11 @@ gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
|
|||
GstRtpH264Pay * rtph264pay, GstClockTime dts, GstClockTime pts)
|
||||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GList *walk;
|
||||
guint i;
|
||||
|
||||
for (walk = rtph264pay->sps; walk; walk = g_list_next (walk)) {
|
||||
GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
|
||||
for (i = 0; i < rtph264pay->sps->len; i++) {
|
||||
GstBuffer *sps_buf =
|
||||
GST_BUFFER_CAST (g_ptr_array_index (rtph264pay->sps, i));
|
||||
|
||||
GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
|
||||
/* resend SPS */
|
||||
|
@ -830,8 +725,9 @@ gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
|
|||
if (ret != GST_FLOW_OK)
|
||||
GST_WARNING ("Problem pushing SPS");
|
||||
}
|
||||
for (walk = rtph264pay->pps; walk; walk = g_list_next (walk)) {
|
||||
GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
|
||||
for (i = 0; i < rtph264pay->pps->len; i++) {
|
||||
GstBuffer *pps_buf =
|
||||
GST_BUFFER_CAST (g_ptr_array_index (rtph264pay->pps, i));
|
||||
|
||||
GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
|
||||
/* resend PPS */
|
||||
|
|
|
@ -59,7 +59,7 @@ struct _GstRtpH264Pay
|
|||
GstRTPBasePayload payload;
|
||||
|
||||
guint profile;
|
||||
GList *sps, *pps;
|
||||
GPtrArray *sps, *pps;
|
||||
|
||||
GstH264StreamFormat stream_format;
|
||||
GstH264Alignment alignment;
|
||||
|
|
Loading…
Reference in a new issue