diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c index 32158e4915..cca432d918 100644 --- a/gst/audioparsers/gstac3parse.c +++ b/gst/audioparsers/gstac3parse.c @@ -200,6 +200,7 @@ gst_ac3_parse_reset (GstAc3Parse * ac3parse) { ac3parse->channels = -1; ac3parse->sample_rate = -1; + ac3parse->blocks = -1; ac3parse->eac = FALSE; } @@ -499,13 +500,14 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) GstAc3Parse *ac3parse = GST_AC3_PARSE (parse); GstBuffer *buf = frame->buffer; guint fsize, rate, chans, blocks, sid; - gboolean eac; + gboolean eac, update_rate = FALSE; if (!gst_ac3_parse_frame_header (ac3parse, buf, &fsize, &rate, &chans, &blocks, &sid, &eac)) goto broken_header; - GST_LOG_OBJECT (parse, "size: %u, rate: %u, chans: %u", fsize, rate, chans); + GST_LOG_OBJECT (parse, "size: %u, blocks: %u, rate: %u, chans: %u", fsize, + blocks, rate, chans); if (G_UNLIKELY (sid)) { /* dependent frame, no need to (ac)count for or consider further */ @@ -533,9 +535,18 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) ac3parse->channels = chans; ac3parse->eac = eac; - gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2); + update_rate = TRUE; } + if (G_UNLIKELY (ac3parse->blocks != blocks)) { + ac3parse->blocks = blocks; + + update_rate = TRUE; + } + + if (G_UNLIKELY (update_rate)) + gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2); + return GST_FLOW_OK; /* ERRORS */ diff --git a/gst/audioparsers/gstac3parse.h b/gst/audioparsers/gstac3parse.h index 6ed01ddf50..13270bb8ad 100644 --- a/gst/audioparsers/gstac3parse.h +++ b/gst/audioparsers/gstac3parse.h @@ -53,6 +53,7 @@ struct _GstAc3Parse { /*< private >*/ gint sample_rate; gint channels; + gint blocks; gboolean eac; }; diff --git a/gst/rtp/Makefile.am b/gst/rtp/Makefile.am index 3064a5e0ec..bfdc5d81b1 100644 --- a/gst/rtp/Makefile.am +++ b/gst/rtp/Makefile.am @@ -86,6 +86,7 @@ libgstrtp_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ -lgstvideo-@GST_MAJORMINOR@ \ -lgsttag-@GST_MAJORMINOR@ \ -lgstrtp-@GST_MAJORMINOR@ \ + -lgstpbutils-@GST_MAJORMINOR@ \ $(GST_BASE_LIBS) $(GST_LIBS) \ $(WINSOCK2_LIBS) $(LIBM) libgstrtp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst/rtp/gstrtph264pay.c b/gst/rtp/gstrtph264pay.c index 10548798bc..c149f62ef5 100644 --- a/gst/rtp/gstrtph264pay.c +++ b/gst/rtp/gstrtph264pay.c @@ -22,8 +22,10 @@ #endif #include +#include #include +#include #include "gstrtph264pay.h" @@ -108,6 +110,8 @@ static void gst_rtp_h264_pay_set_property (GObject * object, guint prop_id, static void gst_rtp_h264_pay_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static GstCaps *gst_rtp_h264_pay_getcaps (GstBaseRTPPayload * payload, + GstPad * pad); static gboolean gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps); static GstFlowReturn gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * pad, @@ -186,6 +190,7 @@ gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_basertppayload_change_state); + gstbasertppayload_class->get_caps = gst_rtp_h264_pay_getcaps; gstbasertppayload_class->set_caps = gst_rtp_h264_pay_setcaps; gstbasertppayload_class->handle_buffer = gst_rtp_h264_pay_handle_buffer; gstbasertppayload_class->handle_event = gst_rtp_h264_pay_handle_event; @@ -238,6 +243,123 @@ gst_rtp_h264_pay_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static const gchar *all_levels[] = { + "1", + "1b", + "1.1", + "1.2", + "1.3", + "2", + "2.1", + "2.2", + "3", + "3.1", + "3.2", + "4", + "4.1", + "4.2", + "5", + "5.1", + NULL +}; + +static GstCaps * +gst_rtp_h264_pay_getcaps (GstBaseRTPPayload * payload, GstPad * pad) +{ + GstCaps *allowed_caps; + + allowed_caps = + gst_pad_peer_get_caps_reffed (GST_BASE_RTP_PAYLOAD_SRCPAD (payload)); + + if (allowed_caps) { + GstCaps *caps = NULL; + guint i; + + if (gst_caps_is_any (allowed_caps)) { + gst_caps_unref (allowed_caps); + goto any; + } + + if (gst_caps_is_empty (allowed_caps)) + return allowed_caps; + + caps = gst_caps_new_empty (); + + for (i = 0; i < gst_caps_get_size (allowed_caps); i++) { + GstStructure *s = gst_caps_get_structure (allowed_caps, i); + GstStructure *new_s = gst_structure_new ("video/x-h264", NULL); + const gchar *profile_level_id; + + profile_level_id = gst_structure_get_string (s, "profile-level-id"); + + if (profile_level_id && strlen (profile_level_id) == 6) { + const gchar *profile; + const gchar *level; + long int spsint; + guint8 sps[3]; + + spsint = strtol (profile_level_id, NULL, 16); + sps[0] = spsint >> 16; + sps[1] = spsint >> 8; + sps[2] = spsint; + + profile = gst_codec_utils_h264_get_profile (sps, 3); + level = gst_codec_utils_h264_get_level (sps, 3); + + if (profile && level) { + GST_LOG_OBJECT (payload, "In caps, have profile %s and level %s", + profile, level); + + if (!strcmp (profile, "constrained-baseline")) + gst_structure_set (new_s, "profile", G_TYPE_STRING, profile, NULL); + else { + GValue val = { 0, }; + GValue profiles = { 0, }; + + g_value_init (&profiles, GST_TYPE_LIST); + g_value_init (&val, G_TYPE_STRING); + + g_value_set_static_string (&val, profile); + gst_value_list_append_value (&profiles, &val); + + g_value_set_static_string (&val, "constrained-baseline"); + gst_value_list_append_value (&profiles, &val); + + gst_structure_take_value (new_s, "profile", &profiles); + } + + if (!strcmp (level, "1")) + gst_structure_set (new_s, "level", G_TYPE_STRING, level, NULL); + else { + GValue levels = { 0, }; + GValue val = { 0, }; + int j; + + g_value_init (&levels, GST_TYPE_LIST); + g_value_init (&val, G_TYPE_STRING); + + for (j = 0; all_levels[j]; j++) { + g_value_set_static_string (&val, all_levels[j]); + gst_value_list_prepend_value (&levels, &val); + if (!strcmp (level, all_levels[j])) + break; + } + gst_structure_take_value (new_s, "level", &levels); + } + } + } + + gst_caps_merge_structure (caps, new_s); + } + + gst_caps_unref (allowed_caps); + return caps; + } + +any: + return gst_caps_new_simple ("video/x-h264", NULL); +} + /* take the currently configured SPS and PPS lists and set them on the caps as * sprop-parameter-sets */ static gboolean diff --git a/gst/rtp/gstrtppcmadepay.c b/gst/rtp/gstrtppcmadepay.c index 4d4a80ede3..62fe4b97dc 100644 --- a/gst/rtp/gstrtppcmadepay.c +++ b/gst/rtp/gstrtppcmadepay.c @@ -45,12 +45,12 @@ static GstStaticPadTemplate gst_rtp_pcma_depay_sink_template = GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " - "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"PCMA\";" + "payload = (int) " GST_RTP_PAYLOAD_PCMA_STRING ", " + "clock-rate = (int) 8000, encoding-name = (string) \"PCMA\";" "application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) " GST_RTP_PAYLOAD_PCMA_STRING ", " - "clock-rate = (int) [1, MAX ]") + "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " + "clock-rate = (int) [1, MAX ], encoding-name = (string) \"PCMA\"") ); static GstStaticPadTemplate gst_rtp_pcma_depay_src_template = diff --git a/gst/rtp/gstrtppcmapay.c b/gst/rtp/gstrtppcmapay.c index 6b53dec54e..75d12e816b 100644 --- a/gst/rtp/gstrtppcmapay.c +++ b/gst/rtp/gstrtppcmapay.c @@ -47,7 +47,7 @@ static GstStaticPadTemplate gst_rtp_pcma_pay_src_template = "application/x-rtp, " "media = (string) \"audio\", " "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " - "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMA\"") + "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"PCMA\"") ); static gboolean gst_rtp_pcma_pay_setcaps (GstBaseRTPPayload * payload, diff --git a/gst/rtp/gstrtppcmudepay.c b/gst/rtp/gstrtppcmudepay.c index 36dfd46ef1..9a444063f9 100644 --- a/gst/rtp/gstrtppcmudepay.c +++ b/gst/rtp/gstrtppcmudepay.c @@ -45,12 +45,12 @@ static GstStaticPadTemplate gst_rtp_pcmu_depay_sink_template = GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " - "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"PCMU\";" + "payload = (int) " GST_RTP_PAYLOAD_PCMU_STRING ", " + "encoding-name = (string) \"PCMU\", clock-rate = (int) 8000; " "application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) " GST_RTP_PAYLOAD_PCMU_STRING ", " - "clock-rate = (int) [1, MAX ]") + "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " + "encoding-name = (string) \"PCMU\", clock-rate = (int) [1, MAX ]") ); static GstStaticPadTemplate gst_rtp_pcmu_depay_src_template = diff --git a/gst/rtp/gstrtppcmupay.c b/gst/rtp/gstrtppcmupay.c index 6b40a20300..665fba714d 100644 --- a/gst/rtp/gstrtppcmupay.c +++ b/gst/rtp/gstrtppcmupay.c @@ -47,7 +47,7 @@ static GstStaticPadTemplate gst_rtp_pcmu_pay_src_template = "application/x-rtp, " "media = (string) \"audio\", " "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " - "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMU\"") + "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"PCMU\"") ); static gboolean gst_rtp_pcmu_pay_setcaps (GstBaseRTPPayload * payload, diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index bf7c45a39f..f20230889a 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -5965,8 +5965,12 @@ gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment, gboolean async) * udp sources */ gst_rtspsrc_send_dummy_packets (src); - /* activate receive elements */ - gst_element_set_state (GST_ELEMENT_CAST (src), GST_STATE_PLAYING); + /* activate receive elements; + * only in async case, since receive elements may not have been affected + * by overall state change (e.g. not around yet), + * do not mess with state in sync case (e.g. seeking) */ + if (async) + gst_element_set_state (GST_ELEMENT_CAST (src), GST_STATE_PLAYING); /* construct a control url */ if (src->control)