mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 00:31:13 +00:00
rtpbasepayload: Implement video SDP attributes
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=726472
This commit is contained in:
parent
476dff826e
commit
042e71a117
2 changed files with 130 additions and 1 deletions
|
@ -60,6 +60,7 @@ struct _GstRTPBasePayloadPrivate
|
||||||
GstEvent *pending_segment;
|
GstEvent *pending_segment;
|
||||||
|
|
||||||
GstCaps *subclass_srccaps;
|
GstCaps *subclass_srccaps;
|
||||||
|
GstCaps *sinkcaps;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* RTPBasePayload signals and args */
|
/* RTPBasePayload signals and args */
|
||||||
|
@ -403,6 +404,7 @@ gst_rtp_base_payload_finalize (GObject * object)
|
||||||
rtpbasepayload->encoding_name = NULL;
|
rtpbasepayload->encoding_name = NULL;
|
||||||
|
|
||||||
gst_caps_replace (&rtpbasepayload->priv->subclass_srccaps, NULL);
|
gst_caps_replace (&rtpbasepayload->priv->subclass_srccaps, NULL);
|
||||||
|
gst_caps_replace (&rtpbasepayload->priv->sinkcaps, NULL);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -450,6 +452,8 @@ gst_rtp_base_payload_sink_event_default (GstRTPBasePayload * rtpbasepayload,
|
||||||
gst_event_parse_caps (event, &caps);
|
gst_event_parse_caps (event, &caps);
|
||||||
GST_DEBUG_OBJECT (rtpbasepayload, "setting caps %" GST_PTR_FORMAT, caps);
|
GST_DEBUG_OBJECT (rtpbasepayload, "setting caps %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
|
gst_caps_replace (&rtpbasepayload->priv->sinkcaps, caps);
|
||||||
|
|
||||||
rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
|
rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
|
||||||
if (rtpbasepayload_class->set_caps)
|
if (rtpbasepayload_class->set_caps)
|
||||||
res = rtpbasepayload_class->set_caps (rtpbasepayload, caps);
|
res = rtpbasepayload_class->set_caps (rtpbasepayload, caps);
|
||||||
|
@ -775,6 +779,7 @@ static gboolean
|
||||||
gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload)
|
gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload)
|
||||||
{
|
{
|
||||||
GstCaps *templ, *peercaps, *srccaps;
|
GstCaps *templ, *peercaps, *srccaps;
|
||||||
|
GstStructure *s, *d;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
|
|
||||||
payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
|
payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
|
||||||
|
@ -806,7 +811,6 @@ gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload)
|
||||||
GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps);
|
GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps);
|
||||||
} else {
|
} else {
|
||||||
GstCaps *temp;
|
GstCaps *temp;
|
||||||
GstStructure *s, *d;
|
|
||||||
const GValue *value;
|
const GValue *value;
|
||||||
gboolean have_pt = FALSE;
|
gboolean have_pt = FALSE;
|
||||||
gboolean have_ts_offset = FALSE;
|
gboolean have_ts_offset = FALSE;
|
||||||
|
@ -1029,6 +1033,35 @@ gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload)
|
||||||
GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
|
GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (payload->priv->sinkcaps != NULL) {
|
||||||
|
s = gst_caps_get_structure (payload->priv->sinkcaps, 0);
|
||||||
|
if (g_str_has_prefix (gst_structure_get_name (s), "video")) {
|
||||||
|
gboolean has_framerate;
|
||||||
|
gint num, denom;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (payload, "video caps: %" GST_PTR_FORMAT,
|
||||||
|
payload->priv->sinkcaps);
|
||||||
|
|
||||||
|
has_framerate = gst_structure_get_fraction (s, "framerate", &num, &denom);
|
||||||
|
if (has_framerate && num == 0 && denom == 1) {
|
||||||
|
has_framerate =
|
||||||
|
gst_structure_get_fraction (s, "max-framerate", &num, &denom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_framerate) {
|
||||||
|
gchar str[G_ASCII_DTOSTR_BUF_SIZE];
|
||||||
|
gdouble framerate;
|
||||||
|
|
||||||
|
gst_util_fraction_to_double (num, denom, &framerate);
|
||||||
|
g_ascii_dtostr (str, G_ASCII_DTOSTR_BUF_SIZE, framerate);
|
||||||
|
d = gst_caps_get_structure (srccaps, 0);
|
||||||
|
gst_structure_set (d, "a-framerate", G_TYPE_STRING, str, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (payload, "with video caps: %" GST_PTR_FORMAT, srccaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update_max_ptime (payload);
|
update_max_ptime (payload);
|
||||||
|
|
||||||
res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps);
|
res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps);
|
||||||
|
@ -1493,6 +1526,7 @@ gst_rtp_base_payload_change_state (GstElement * element,
|
||||||
priv->base_offset = GST_BUFFER_OFFSET_NONE;
|
priv->base_offset = GST_BUFFER_OFFSET_NONE;
|
||||||
priv->negotiated = FALSE;
|
priv->negotiated = FALSE;
|
||||||
gst_caps_replace (&rtpbasepayload->priv->subclass_srccaps, NULL);
|
gst_caps_replace (&rtpbasepayload->priv->subclass_srccaps, NULL);
|
||||||
|
gst_caps_replace (&rtpbasepayload->priv->sinkcaps, NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -287,6 +287,14 @@ validate_event (guint index, const gchar * name, const gchar * field, ...)
|
||||||
fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
|
fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
|
||||||
"ssrc", &ssrc));
|
"ssrc", &ssrc));
|
||||||
fail_unless_equals_int (ssrc, expected);
|
fail_unless_equals_int (ssrc, expected);
|
||||||
|
} else if (!g_strcmp0 (field, "a-framerate")) {
|
||||||
|
const gchar *expected = va_arg (var_args, const gchar *);
|
||||||
|
GstCaps *caps;
|
||||||
|
const gchar *framerate;
|
||||||
|
gst_event_parse_caps (event, &caps);
|
||||||
|
framerate = gst_structure_get_string (gst_caps_get_structure (caps, 0),
|
||||||
|
"a-framerate");
|
||||||
|
fail_unless_equals_string (framerate, expected);
|
||||||
} else {
|
} else {
|
||||||
fail ("test cannot validate unknown event field '%s'", field);
|
fail ("test cannot validate unknown event field '%s'", field);
|
||||||
}
|
}
|
||||||
|
@ -1764,6 +1772,90 @@ GST_START_TEST (rtp_base_payload_property_stats_test)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* push a single buffer to the payloader which should successfully payload it
|
||||||
|
* into an RTP packet. besides the payloaded RTP packet there should be the
|
||||||
|
* three events initial events: stream-start, caps and segment. because of that
|
||||||
|
* the input caps has framerate this will be propagated to an a-framerate field
|
||||||
|
* on the output caps.
|
||||||
|
*/
|
||||||
|
GST_START_TEST (rtp_base_payload_framerate_attribute)
|
||||||
|
{
|
||||||
|
State *state;
|
||||||
|
|
||||||
|
state = create_payloader ("video/x-raw,framerate=(fraction)1/4", &sinktmpl,
|
||||||
|
"perfect-rtptime", FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
set_state (state, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
push_buffer (state,
|
||||||
|
"pts", 0 * GST_SECOND,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
set_state (state, GST_STATE_NULL);
|
||||||
|
|
||||||
|
validate_buffers_received (1);
|
||||||
|
|
||||||
|
validate_buffer (0,
|
||||||
|
"pts", 0 * GST_SECOND,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
validate_events_received (3);
|
||||||
|
|
||||||
|
validate_normal_start_events (0);
|
||||||
|
|
||||||
|
validate_event (1, "caps",
|
||||||
|
"a-framerate", "0.25",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
destroy_payloader (state);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* push a single buffer to the payloader which should successfully payload it
|
||||||
|
* into an RTP packet. besides the payloaded RTP packet there should be the
|
||||||
|
* three events initial events: stream-start, caps and segment. because of that
|
||||||
|
* the input caps has both framerate and max-framerate set the a-framerate field
|
||||||
|
* on the output caps will correspond to the value of the max-framerate field.
|
||||||
|
*/
|
||||||
|
GST_START_TEST (rtp_base_payload_max_framerate_attribute)
|
||||||
|
{
|
||||||
|
State *state;
|
||||||
|
|
||||||
|
state = create_payloader (
|
||||||
|
"video/x-raw,framerate=(fraction)0/1,max-framerate=(fraction)1/8",
|
||||||
|
&sinktmpl,
|
||||||
|
"perfect-rtptime", FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
set_state (state, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
push_buffer (state,
|
||||||
|
"pts", 0 * GST_SECOND,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
set_state (state, GST_STATE_NULL);
|
||||||
|
|
||||||
|
validate_buffers_received (1);
|
||||||
|
|
||||||
|
validate_buffer (0,
|
||||||
|
"pts", 0 * GST_SECOND,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
validate_events_received (3);
|
||||||
|
|
||||||
|
validate_normal_start_events (0);
|
||||||
|
|
||||||
|
validate_event (1, "caps",
|
||||||
|
"a-framerate", "0.125",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
destroy_payloader (state);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
rtp_basepayloading_suite (void)
|
rtp_basepayloading_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -1798,6 +1890,9 @@ rtp_basepayloading_suite (void)
|
||||||
tcase_add_test (tc_chain, rtp_base_payload_property_ptime_multiple_test);
|
tcase_add_test (tc_chain, rtp_base_payload_property_ptime_multiple_test);
|
||||||
tcase_add_test (tc_chain, rtp_base_payload_property_stats_test);
|
tcase_add_test (tc_chain, rtp_base_payload_property_stats_test);
|
||||||
|
|
||||||
|
tcase_add_test (tc_chain, rtp_base_payload_framerate_attribute);
|
||||||
|
tcase_add_test (tc_chain, rtp_base_payload_max_framerate_attribute);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue