mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
gst/realmedia/rdtdepay.*: Parse other values from the incomming caps.
Original commit message from CVS: * gst/realmedia/rdtdepay.c: (gst_rdt_depay_init), (gst_rdt_depay_setcaps), (gst_rdt_depay_sink_event), (create_segment_event), (gst_rdt_depay_push), (gst_rdt_depay_handle_data), (gst_rdt_depay_change_state): * gst/realmedia/rdtdepay.h: Parse other values from the incomming caps. Add event handler to handle flushing and segments. Create segment events. * gst/realmedia/rdtjitterbuffer.c: (rdt_jitter_buffer_insert): Do skew correction based on RDT timestamps. * gst/realmedia/rdtmanager.c: (activate_session), (gst_rdt_manager_parse_caps), (gst_rdt_manager_setcaps), (create_recv_rtp): Parse caps to get the clockrate needed for the jitterbuffer. * gst/realmedia/rmdemux.c: (gst_rmdemux_parse_video_packet): Apply timestamp fixup after correcting for initial timestamp and internal base timestamp corrections.
This commit is contained in:
parent
35b3e2b596
commit
ff1503f5cf
6 changed files with 236 additions and 19 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
2008-08-27 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||
|
||||
* gst/realmedia/rdtdepay.c: (gst_rdt_depay_init),
|
||||
(gst_rdt_depay_setcaps), (gst_rdt_depay_sink_event),
|
||||
(create_segment_event), (gst_rdt_depay_push),
|
||||
(gst_rdt_depay_handle_data), (gst_rdt_depay_change_state):
|
||||
* gst/realmedia/rdtdepay.h:
|
||||
Parse other values from the incomming caps.
|
||||
Add event handler to handle flushing and segments.
|
||||
Create segment events.
|
||||
|
||||
* gst/realmedia/rdtjitterbuffer.c: (rdt_jitter_buffer_insert):
|
||||
Do skew correction based on RDT timestamps.
|
||||
|
||||
* gst/realmedia/rdtmanager.c: (activate_session),
|
||||
(gst_rdt_manager_parse_caps), (gst_rdt_manager_setcaps),
|
||||
(create_recv_rtp):
|
||||
Parse caps to get the clockrate needed for the jitterbuffer.
|
||||
|
||||
* gst/realmedia/rmdemux.c: (gst_rmdemux_parse_video_packet):
|
||||
Apply timestamp fixup after correcting for initial timestamp and
|
||||
internal base timestamp corrections.
|
||||
|
||||
2008-08-27 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||
|
||||
* gst/realmedia/rdtdepay.c: (gst_rdt_depay_handle_data),
|
||||
|
|
|
@ -84,6 +84,7 @@ static GstStateChangeReturn gst_rdt_depay_change_state (GstElement *
|
|||
element, GstStateChange transition);
|
||||
|
||||
static gboolean gst_rdt_depay_setcaps (GstPad * pad, GstCaps * caps);
|
||||
static gboolean gst_rdt_depay_sink_event (GstPad * pad, GstEvent * event);
|
||||
static GstFlowReturn gst_rdt_depay_chain (GstPad * pad, GstBuffer * buf);
|
||||
|
||||
static void
|
||||
|
@ -127,6 +128,7 @@ gst_rdt_depay_init (GstRDTDepay * rdtdepay, GstRDTDepayClass * klass)
|
|||
rdtdepay->sinkpad =
|
||||
gst_pad_new_from_static_template (&gst_rdt_depay_sink_template, "sink");
|
||||
gst_pad_set_chain_function (rdtdepay->sinkpad, gst_rdt_depay_chain);
|
||||
gst_pad_set_event_function (rdtdepay->sinkpad, gst_rdt_depay_sink_event);
|
||||
gst_pad_set_setcaps_function (rdtdepay->sinkpad, gst_rdt_depay_setcaps);
|
||||
gst_element_add_pad (GST_ELEMENT_CAST (rdtdepay), rdtdepay->sinkpad);
|
||||
|
||||
|
@ -155,7 +157,7 @@ gst_rdt_depay_setcaps (GstPad * pad, GstCaps * caps)
|
|||
GstRDTDepay *rdtdepay;
|
||||
GstCaps *srccaps;
|
||||
gint clock_rate = 1000; /* default */
|
||||
const GValue *config;
|
||||
const GValue *value;
|
||||
GstBuffer *header;
|
||||
|
||||
rdtdepay = GST_RDT_DEPAY (GST_PAD_PARENT (pad));
|
||||
|
@ -166,14 +168,44 @@ gst_rdt_depay_setcaps (GstPad * pad, GstCaps * caps)
|
|||
gst_structure_get_int (structure, "clock-rate", &clock_rate);
|
||||
|
||||
/* config contains the RealMedia header as a buffer. */
|
||||
config = gst_structure_get_value (structure, "config");
|
||||
if (!config)
|
||||
value = gst_structure_get_value (structure, "config");
|
||||
if (!value)
|
||||
goto no_header;
|
||||
|
||||
header = gst_value_get_buffer (config);
|
||||
header = gst_value_get_buffer (value);
|
||||
if (!header)
|
||||
goto no_header;
|
||||
|
||||
/* get other values for newsegment */
|
||||
value = gst_structure_get_value (structure, "npt-start");
|
||||
if (value && G_VALUE_HOLDS_UINT64 (value))
|
||||
rdtdepay->npt_start = g_value_get_uint64 (value);
|
||||
else
|
||||
rdtdepay->npt_start = 0;
|
||||
GST_DEBUG_OBJECT (rdtdepay, "NPT start %" G_GUINT64_FORMAT,
|
||||
rdtdepay->npt_start);
|
||||
|
||||
value = gst_structure_get_value (structure, "npt-stop");
|
||||
if (value && G_VALUE_HOLDS_UINT64 (value))
|
||||
rdtdepay->npt_stop = g_value_get_uint64 (value);
|
||||
else
|
||||
rdtdepay->npt_stop = -1;
|
||||
|
||||
GST_DEBUG_OBJECT (rdtdepay, "NPT stop %" G_GUINT64_FORMAT,
|
||||
rdtdepay->npt_stop);
|
||||
|
||||
value = gst_structure_get_value (structure, "play-speed");
|
||||
if (value && G_VALUE_HOLDS_DOUBLE (value))
|
||||
rdtdepay->play_speed = g_value_get_double (value);
|
||||
else
|
||||
rdtdepay->play_speed = 1.0;
|
||||
|
||||
value = gst_structure_get_value (structure, "play-scale");
|
||||
if (value && G_VALUE_HOLDS_DOUBLE (value))
|
||||
rdtdepay->play_scale = g_value_get_double (value);
|
||||
else
|
||||
rdtdepay->play_scale = 1.0;
|
||||
|
||||
/* caps seem good, configure element */
|
||||
rdtdepay->clock_rate = clock_rate;
|
||||
|
||||
|
@ -196,11 +228,81 @@ no_header:
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rdt_depay_sink_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstRDTDepay *depay;
|
||||
gboolean res = TRUE;
|
||||
|
||||
depay = GST_RDT_DEPAY (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
res = gst_pad_push_event (depay->srcpad, event);
|
||||
|
||||
gst_segment_init (&depay->segment, GST_FORMAT_UNDEFINED);
|
||||
depay->need_newsegment = TRUE;
|
||||
depay->next_seqnum = -1;
|
||||
break;
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
gboolean update;
|
||||
gdouble rate;
|
||||
GstFormat fmt;
|
||||
gint64 start, stop, position;
|
||||
|
||||
gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop,
|
||||
&position);
|
||||
|
||||
gst_segment_set_newsegment (&depay->segment, update, rate, fmt,
|
||||
start, stop, position);
|
||||
|
||||
/* don't pass the event downstream, we generate our own segment
|
||||
* including the NTP time and other things we receive in caps */
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* pass other events forward */
|
||||
res = gst_pad_push_event (depay->srcpad, event);
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstEvent *
|
||||
create_segment_event (GstRDTDepay * depay, gboolean update,
|
||||
GstClockTime position)
|
||||
{
|
||||
GstEvent *event;
|
||||
GstClockTime stop;
|
||||
|
||||
if (depay->npt_stop != -1)
|
||||
stop = depay->npt_stop - depay->npt_start;
|
||||
else
|
||||
stop = -1;
|
||||
|
||||
event = gst_event_new_new_segment_full (update, depay->play_speed,
|
||||
depay->play_scale, GST_FORMAT_TIME, position, stop,
|
||||
position + depay->npt_start);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rdt_depay_push (GstRDTDepay * rdtdepay, GstBuffer * buffer)
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
|
||||
if (rdtdepay->need_newsegment) {
|
||||
GstEvent *event;
|
||||
|
||||
event = create_segment_event (rdtdepay, FALSE, 0);
|
||||
gst_pad_push_event (rdtdepay->srcpad, event);
|
||||
|
||||
rdtdepay->need_newsegment = FALSE;
|
||||
}
|
||||
|
||||
gst_buffer_set_caps (buffer, GST_PAD_CAPS (rdtdepay->srcpad));
|
||||
|
||||
if (rdtdepay->discont) {
|
||||
|
@ -224,7 +326,6 @@ gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime,
|
|||
guint32 timestamp;
|
||||
gint gap;
|
||||
guint16 seqnum;
|
||||
gboolean discont;
|
||||
|
||||
/* get pointers to the packet data */
|
||||
gst_rdt_packet_data_peek_data (packet, &data, &size);
|
||||
|
@ -399,7 +500,9 @@ gst_rdt_depay_change_state (GstElement * element, GstStateChange transition)
|
|||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_segment_init (&rdtdepay->segment, GST_FORMAT_UNDEFINED);
|
||||
rdtdepay->next_seqnum = -1;
|
||||
rdtdepay->need_newsegment = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -47,9 +47,16 @@ struct _GstRDTDepay
|
|||
GstPad *srcpad;
|
||||
|
||||
guint clock_rate;
|
||||
GstClockTime npt_start;
|
||||
GstClockTime npt_stop;
|
||||
gdouble play_speed;
|
||||
gdouble play_scale;
|
||||
|
||||
guint32 next_seqnum;
|
||||
|
||||
gboolean discont;
|
||||
gboolean need_newsegment;
|
||||
GstSegment segment;
|
||||
GstBuffer *header;
|
||||
};
|
||||
|
||||
|
|
|
@ -360,6 +360,10 @@ rdt_jitter_buffer_insert (RDTJitterBuffer * jbuf, GstBuffer * buf,
|
|||
g_return_val_if_fail (more == TRUE, FALSE);
|
||||
|
||||
seqnum = gst_rdt_packet_data_get_seq (&packet);
|
||||
/* do skew calculation by measuring the difference between rtptime and the
|
||||
* receive time, this function will retimestamp @buf with the skew corrected
|
||||
* running time. */
|
||||
rtptime = gst_rdt_packet_data_get_timestamp (&packet);
|
||||
|
||||
/* loop the list to skip strictly smaller seqnum buffers */
|
||||
for (list = jbuf->packets->head; list; list = g_list_next (list)) {
|
||||
|
@ -385,11 +389,7 @@ rdt_jitter_buffer_insert (RDTJitterBuffer * jbuf, GstBuffer * buf,
|
|||
break;
|
||||
}
|
||||
|
||||
/* do skew calculation by measuring the difference between rtptime and the
|
||||
* receive time, this function will retimestamp @buf with the skew corrected
|
||||
* running time. */
|
||||
//rtptime = gst_rtp_buffer_get_timestamp (buf);
|
||||
rtptime = 0;
|
||||
|
||||
if (clock_rate) {
|
||||
time = calculate_skew (jbuf, rtptime, time, clock_rate);
|
||||
GST_BUFFER_TIMESTAMP (buf) = time;
|
||||
|
|
|
@ -136,6 +136,10 @@ static GstPad *gst_rdt_manager_request_new_pad (GstElement * element,
|
|||
GstPadTemplate * templ, const gchar * name);
|
||||
static void gst_rdt_manager_release_pad (GstElement * element, GstPad * pad);
|
||||
|
||||
static gboolean gst_rdt_manager_parse_caps (GstRDTManager * rdtmanager,
|
||||
GstRDTManagerSession * session, GstCaps * caps);
|
||||
static gboolean gst_rdt_manager_setcaps (GstPad * pad, GstCaps * caps);
|
||||
|
||||
static GstFlowReturn gst_rdt_manager_chain_rdt (GstPad * pad,
|
||||
GstBuffer * buffer);
|
||||
static GstFlowReturn gst_rdt_manager_chain_rtcp (GstPad * pad,
|
||||
|
@ -181,6 +185,7 @@ struct _GstRDTManagerSession
|
|||
guint8 pt;
|
||||
gint clock_rate;
|
||||
GstCaps *caps;
|
||||
gint64 clock_base;
|
||||
|
||||
GstSegment segment;
|
||||
|
||||
|
@ -279,7 +284,14 @@ activate_session (GstRDTManager * rdtmanager, GstRDTManagerSession * session,
|
|||
g_signal_emitv (args, gst_rdt_manager_signals[SIGNAL_REQUEST_PT_MAP], 0,
|
||||
&ret);
|
||||
|
||||
caps = (GstCaps *) g_value_get_boxed (&ret);
|
||||
g_value_unset (&args[0]);
|
||||
g_value_unset (&args[1]);
|
||||
g_value_unset (&args[2]);
|
||||
caps = (GstCaps *) g_value_dup_boxed (&ret);
|
||||
g_value_unset (&ret);
|
||||
|
||||
if (caps)
|
||||
gst_rdt_manager_parse_caps (rdtmanager, session, caps);
|
||||
|
||||
name = g_strdup_printf ("recv_rtp_src_%d_%u_%d", session->id, ssrc, pt);
|
||||
klass = GST_ELEMENT_GET_CLASS (rdtmanager);
|
||||
|
@ -288,6 +300,7 @@ activate_session (GstRDTManager * rdtmanager, GstRDTManagerSession * session,
|
|||
g_free (name);
|
||||
|
||||
gst_pad_set_caps (session->recv_rtp_src, caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
gst_pad_set_element_private (session->recv_rtp_src, session);
|
||||
gst_pad_set_query_function (session->recv_rtp_src, gst_rdt_manager_query_src);
|
||||
|
@ -651,6 +664,73 @@ duplicate:
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rdt_manager_parse_caps (GstRDTManager * rdtmanager,
|
||||
GstRDTManagerSession * session, GstCaps * caps)
|
||||
{
|
||||
GstStructure *caps_struct;
|
||||
guint val;
|
||||
|
||||
/* first parse the caps */
|
||||
caps_struct = gst_caps_get_structure (caps, 0);
|
||||
|
||||
GST_DEBUG_OBJECT (rdtmanager, "got caps");
|
||||
|
||||
/* we need a clock-rate to convert the rtp timestamps to GStreamer time and to
|
||||
* measure the amount of data in the buffer */
|
||||
if (!gst_structure_get_int (caps_struct, "clock-rate", &session->clock_rate))
|
||||
session->clock_rate = 1000;
|
||||
|
||||
if (session->clock_rate <= 0)
|
||||
goto wrong_rate;
|
||||
|
||||
GST_DEBUG_OBJECT (rdtmanager, "got clock-rate %d", session->clock_rate);
|
||||
|
||||
/* gah, clock-base is uint. If we don't have a base, we will use the first
|
||||
* buffer timestamp as the base time. This will screw up sync but it's better
|
||||
* than nothing. */
|
||||
if (gst_structure_get_uint (caps_struct, "clock-base", &val))
|
||||
session->clock_base = val;
|
||||
else
|
||||
session->clock_base = -1;
|
||||
|
||||
GST_DEBUG_OBJECT (rdtmanager, "got clock-base %" G_GINT64_FORMAT,
|
||||
session->clock_base);
|
||||
|
||||
/* first expected seqnum */
|
||||
if (gst_structure_get_uint (caps_struct, "seqnum-base", &val))
|
||||
session->next_seqnum = val;
|
||||
else
|
||||
session->next_seqnum = -1;
|
||||
|
||||
GST_DEBUG_OBJECT (rdtmanager, "got seqnum-base %d", session->next_seqnum);
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
wrong_rate:
|
||||
{
|
||||
GST_DEBUG_OBJECT (rdtmanager, "Invalid clock-rate %d", session->clock_rate);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rdt_manager_setcaps (GstPad * pad, GstCaps * caps)
|
||||
{
|
||||
GstRDTManager *rdtmanager;
|
||||
GstRDTManagerSession *session;
|
||||
gboolean res;
|
||||
|
||||
rdtmanager = GST_RDT_MANAGER (GST_PAD_PARENT (pad));
|
||||
/* find session */
|
||||
session = gst_pad_get_element_private (pad);
|
||||
|
||||
res = gst_rdt_manager_parse_caps (rdtmanager, session, caps);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rdt_manager_chain_rdt (GstPad * pad, GstBuffer * buffer)
|
||||
{
|
||||
|
@ -1072,6 +1152,8 @@ create_recv_rtp (GstRDTManager * rdtmanager, GstPadTemplate * templ,
|
|||
|
||||
session->recv_rtp_sink = gst_pad_new_from_template (templ, name);
|
||||
gst_pad_set_element_private (session->recv_rtp_sink, session);
|
||||
gst_pad_set_setcaps_function (session->recv_rtp_sink,
|
||||
gst_rdt_manager_setcaps);
|
||||
gst_pad_set_chain_function (session->recv_rtp_sink,
|
||||
gst_rdt_manager_chain_rdt);
|
||||
gst_pad_set_active (session->recv_rtp_sink, TRUE);
|
||||
|
|
|
@ -2311,17 +2311,19 @@ gst_rmdemux_parse_video_packet (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
|
|||
stream->frag_length = 0;
|
||||
|
||||
gst_buffer_set_caps (out, GST_PAD_CAPS (stream->pad));
|
||||
|
||||
if (timestamp != -1) {
|
||||
if (rmdemux->first_ts != -1 && timestamp > rmdemux->first_ts)
|
||||
timestamp -= rmdemux->first_ts;
|
||||
else
|
||||
timestamp = 0;
|
||||
|
||||
if (rmdemux->base_ts != -1)
|
||||
timestamp += rmdemux->base_ts;
|
||||
}
|
||||
timestamp =
|
||||
gst_rmdemux_fix_timestamp (rmdemux, stream, outdata, timestamp);
|
||||
|
||||
if (rmdemux->first_ts != -1 && timestamp > rmdemux->first_ts)
|
||||
timestamp -= rmdemux->first_ts;
|
||||
else
|
||||
timestamp = 0;
|
||||
|
||||
if (rmdemux->base_ts != -1)
|
||||
timestamp += rmdemux->base_ts;
|
||||
|
||||
GST_BUFFER_TIMESTAMP (out) = timestamp;
|
||||
|
||||
GST_LOG_OBJECT (rmdemux, "pushing timestamp %" GST_TIME_FORMAT,
|
||||
|
|
Loading…
Reference in a new issue