static GstFlowReturn gst_rdt_depay_chain (GstPad * pad, GstBuffer * buf) { GstRDTDepay *rdtdepay; GstFlowReturn ret; GstClockTime timestamp; gboolean more; GstRDTPacket packet; rdtdepay = GST_RDT_DEPAY (GST_PAD_PARENT (pad)); if (GST_BUFFER_IS_DISCONT (buf)) { GST_LOG_OBJECT (rdtdepay, "received discont"); rdtdepay->discont = TRUE; } if (rdtdepay->header) { GstBuffer *out; out = rdtdepay->header; rdtdepay->header = NULL; /* push header data first */ ret = gst_rdt_depay_push (rdtdepay, out); } /* save timestamp */ timestamp = GST_BUFFER_TIMESTAMP (buf); ret = GST_FLOW_OK; GST_LOG_OBJECT (rdtdepay, "received buffer timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); /* data is in RDT format. */ more = gst_rdt_buffer_get_first_packet (buf, &packet); while (more) { GstRDTType type; type = gst_rdt_packet_get_type (&packet); GST_DEBUG_OBJECT (rdtdepay, "Have packet of type %04x", type); if (GST_RDT_IS_DATA_TYPE (type)) { GST_DEBUG_OBJECT (rdtdepay, "We have a data packet"); ret = gst_rdt_depay_handle_data (rdtdepay, timestamp, &packet); } else { switch (type) { default: GST_DEBUG_OBJECT (rdtdepay, "Ignoring packet"); break; } } if (ret != GST_FLOW_OK) break; more = gst_rdt_packet_move_to_next (&packet); } return ret; }
static GstStateChangeReturn gst_rdt_depay_change_state (GstElement * element, GstStateChange transition) { GstRDTDepay *rdtdepay; GstStateChangeReturn ret; rdtdepay = GST_RDT_DEPAY (element); switch (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; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: if (rdtdepay->header) gst_buffer_unref (rdtdepay->header); rdtdepay->header = NULL; break; case GST_STATE_CHANGE_READY_TO_NULL: break; default: break; } return ret; }
static void gst_rdt_depay_finalize (GObject * object) { GstRDTDepay *rdtdepay; rdtdepay = GST_RDT_DEPAY (object); if (rdtdepay->header) gst_buffer_unref (rdtdepay->header); G_OBJECT_CLASS (parent_class)->finalize (object); }
static void gst_rdt_depay_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstRDTDepay *rdtdepay; rdtdepay = GST_RDT_DEPAY (object); switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
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 gboolean gst_rdt_depay_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstRDTDepay *depay; gboolean res = TRUE; depay = GST_RDT_DEPAY (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); res = gst_rdt_depay_setcaps (pad, caps); gst_event_unref (event); break; } 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_SEGMENT: { gst_event_copy_segment (event, &depay->segment); /* 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 gboolean gst_rdt_depay_setcaps (GstPad * pad, GstCaps * caps) { GstStructure *structure; GstRDTDepay *rdtdepay; GstCaps *srccaps; gint clock_rate = 1000; /* default */ const GValue *value; GstBuffer *header; rdtdepay = GST_RDT_DEPAY (GST_PAD_PARENT (pad)); structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_field (structure, "clock-rate")) gst_structure_get_int (structure, "clock-rate", &clock_rate); /* config contains the RealMedia header as a buffer. */ value = gst_structure_get_value (structure, "config"); if (!value) goto no_header; 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; /* set caps on pad and on header */ srccaps = gst_caps_new_empty_simple ("application/vnd.rn-realmedia"); gst_pad_set_caps (rdtdepay->srcpad, srccaps); gst_caps_unref (srccaps); if (rdtdepay->header) gst_buffer_unref (rdtdepay->header); rdtdepay->header = gst_buffer_ref (header); return TRUE; /* ERRORS */ no_header: { GST_ERROR_OBJECT (rdtdepay, "no header found in caps, no 'config' field"); return FALSE; } }