GstEvent *pending_segment;
GstCaps *subclass_srccaps;
+ GstCaps *sinkcaps;
};
/* RTPBasePayload signals and args */
rtpbasepayload->encoding_name = NULL;
gst_caps_replace (&rtpbasepayload->priv->subclass_srccaps, NULL);
+ gst_caps_replace (&rtpbasepayload->priv->sinkcaps, NULL);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
gst_event_parse_caps (event, &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);
if (rtpbasepayload_class->set_caps)
res = rtpbasepayload_class->set_caps (rtpbasepayload, caps);
gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload)
{
GstCaps *templ, *peercaps, *srccaps;
+ GstStructure *s, *d;
gboolean res;
payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps);
} else {
GstCaps *temp;
- GstStructure *s, *d;
const GValue *value;
gboolean have_pt = FALSE;
gboolean have_ts_offset = FALSE;
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);
res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps);
priv->base_offset = GST_BUFFER_OFFSET_NONE;
priv->negotiated = FALSE;
gst_caps_replace (&rtpbasepayload->priv->subclass_srccaps, NULL);
+ gst_caps_replace (&rtpbasepayload->priv->sinkcaps, NULL);
break;
default:
break;
fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
"ssrc", &ssrc));
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 {
fail ("test cannot validate unknown event field '%s'", field);
}
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 *
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_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;
}