📄 gstbasesink.c
字号:
}static GstFlowReturngst_base_sink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf){ GstBaseSinkClass *bclass; GstBaseSink *bsink; GstFlowReturn result = GST_FLOW_OK; bsink = GST_BASE_SINK (gst_pad_get_parent (pad)); bclass = GST_BASE_SINK_GET_CLASS (bsink); if (bclass->buffer_alloc) result = bclass->buffer_alloc (bsink, offset, size, caps, buf); else *buf = NULL; /* fallback in gstpad.c will allocate generic buffer */ gst_object_unref (bsink); return result;}static voidgst_base_sink_init (GstBaseSink * basesink, gpointer g_class){ GstPadTemplate *pad_template; GstBaseSinkPrivate *priv; basesink->priv = priv = GST_BASE_SINK_GET_PRIVATE (basesink); pad_template = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); g_return_if_fail (pad_template != NULL); basesink->sinkpad = gst_pad_new_from_template (pad_template, "sink"); gst_pad_set_getcaps_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_pad_getcaps)); gst_pad_set_setcaps_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_pad_setcaps)); gst_pad_set_fixatecaps_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_pad_fixate)); gst_pad_set_bufferalloc_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_pad_buffer_alloc)); gst_pad_set_activate_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_pad_activate)); gst_pad_set_activatepush_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_pad_activate_push)); gst_pad_set_activatepull_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_pad_activate_pull)); gst_pad_set_event_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_event)); gst_pad_set_chain_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_base_sink_chain)); gst_element_add_pad (GST_ELEMENT_CAST (basesink), basesink->sinkpad); basesink->pad_mode = GST_ACTIVATE_NONE; basesink->preroll_queue = g_queue_new (); basesink->abidata.ABI.clip_segment = gst_segment_new (); basesink->can_activate_push = DEFAULT_CAN_ACTIVATE_PUSH; basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL; basesink->sync = DEFAULT_SYNC; basesink->abidata.ABI.max_lateness = DEFAULT_MAX_LATENESS; gst_atomic_int_set (&priv->qos_enabled, DEFAULT_QOS); GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);}static voidgst_base_sink_finalize (GObject * object){ GstBaseSink *basesink; basesink = GST_BASE_SINK (object); g_queue_free (basesink->preroll_queue); gst_segment_free (basesink->abidata.ABI.clip_segment); G_OBJECT_CLASS (parent_class)->finalize (object);}/** * gst_base_sink_set_sync: * @sink: the sink * @sync: the new sync value. * * Configures @sink to synchronize on the clock or not. When * @sync is FALSE, incomming samples will be played as fast as * possible. If @sync is TRUE, the timestamps of the incomming * buffers will be used to schedule the exact render time of its * contents. * * Since: 0.10.4 */voidgst_base_sink_set_sync (GstBaseSink * sink, gboolean sync){ GST_OBJECT_LOCK (sink); sink->sync = sync; GST_OBJECT_UNLOCK (sink);}/** * gst_base_sink_get_sync: * @sink: the sink * * Checks if @sink is currently configured to synchronize against the * clock. * * Returns: TRUE if the sink is configured to synchronize against the clock. * * Since: 0.10.4 */gbooleangst_base_sink_get_sync (GstBaseSink * sink){ gboolean res; GST_OBJECT_LOCK (sink); res = sink->sync; GST_OBJECT_UNLOCK (sink); return res;}/** * gst_base_sink_set_max_lateness: * @sink: the sink * @max_lateness: the new max lateness value. * * Sets the new max lateness value to @max_lateness. This value is * used to decide if a buffer should be dropped or not based on the * buffer timestamp and the current clock time. A value of -1 means * an unlimited time. * * Since: 0.10.4 */voidgst_base_sink_set_max_lateness (GstBaseSink * sink, gint64 max_lateness){ GST_OBJECT_LOCK (sink); sink->abidata.ABI.max_lateness = max_lateness; GST_OBJECT_UNLOCK (sink);}/** * gst_base_sink_get_max_lateness: * @sink: the sink * * Gets the max lateness value. See gst_base_sink_set_max_lateness for * more details. * * Returns: The maximum time in nanoseconds that a buffer can be late * before it is dropped and not rendered. A value of -1 means an * unlimited time. * * Since: 0.10.4 */gint64gst_base_sink_get_max_lateness (GstBaseSink * sink){ gint64 res; GST_OBJECT_LOCK (sink); res = sink->abidata.ABI.max_lateness; GST_OBJECT_UNLOCK (sink); return res;}/** * gst_base_sink_set_qos_enabled: * @sink: the sink * @enabled: the new qos value. * * Configures @sink to send Quality-of-Service events upstream. * * Since: 0.10.5 */voidgst_base_sink_set_qos_enabled (GstBaseSink * sink, gboolean enabled){ gst_atomic_int_set (&sink->priv->qos_enabled, enabled);}/** * gst_base_sink_is_qos_enabled: * @sink: the sink * * Checks if @sink is currently configured to send Quality-of-Service events * upstream. * * Returns: TRUE if the sink is configured to perform Quality-of-Service. * * Since: 0.10.5 */gbooleangst_base_sink_is_qos_enabled (GstBaseSink * sink){ gboolean res; res = g_atomic_int_get (&sink->priv->qos_enabled); return res;}/** * gst_base_sink_get_latency: * @sink: the sink * * Get the currently configured latency. * * Returns: The configured latency. * * Since: 0.10.12 */GstClockTimegst_base_sink_get_latency (GstBaseSink * sink){ GstClockTime res; GST_OBJECT_LOCK (sink); res = sink->priv->latency; GST_OBJECT_UNLOCK (sink); return res;}/** * gst_base_sink_query_latency: * @sink: the sink * @live: if the sink is live * @upstream_live: if an upstream element is live * @min_latency: the min latency of the upstream elements * @max_latency: the max latency of the upstream elements * * Query the sink for the latency parameters. The latency will be queried from * the upstream elements. @live will be TRUE if @sink is configured to * synchronize against the clock. @upstream_live will be TRUE if an upstream * element is live. * * If both @live and @upstream_live are TRUE, the sink will want to compensate * for the latency introduced by the upstream elements by setting the * @min_latency to a strictly possitive value. * * This function is mostly used by subclasses. * * Returns: TRUE if the query succeeded. * * Since: 0.10.12 */gbooleangst_base_sink_query_latency (GstBaseSink * sink, gboolean * live, gboolean * upstream_live, GstClockTime * min_latency, GstClockTime * max_latency){ gboolean l, us_live, res; GstClockTime min, max; GstQuery *query; GstClockTime us_min, us_max; /* we are live when we sync to the clock */ l = gst_base_sink_get_sync (sink); /* assume no latency */ min = 0; max = -1; us_live = FALSE; query = gst_query_new_latency (); /* ask the peer for the latency */ if (!(res = gst_base_sink_peer_query (sink, query))) goto query_failed; /* get upstream min and max latency */ gst_query_parse_latency (query, &us_live, &us_min, &us_max); if (us_live) { /* upstream live, use its latency, subclasses should use these * values to create the complete latency. */ min = us_min; max = us_max; } GST_DEBUG_OBJECT (sink, "latency query: live: %d, upstream: %d, min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, l, us_live, GST_TIME_ARGS (min), GST_TIME_ARGS (max)); if (live) *live = l; if (upstream_live) *upstream_live = us_live; if (min_latency) *min_latency = min; if (max_latency) *max_latency = max;done: gst_query_unref (query); return res; /* ERRORS */query_failed: { GST_DEBUG_OBJECT (sink, "latency query failed"); goto done; }}static voidgst_base_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec){ GstBaseSink *sink = GST_BASE_SINK (object); switch (prop_id) { case PROP_PREROLL_QUEUE_LEN: /* preroll lock necessary to serialize with finish_preroll */ GST_PAD_PREROLL_LOCK (sink->sinkpad); sink->preroll_queue_max_len = g_value_get_uint (value); GST_PAD_PREROLL_UNLOCK (sink->sinkpad); break; case PROP_SYNC: gst_base_sink_set_sync (sink, g_value_get_boolean (value)); break; case PROP_MAX_LATENESS: gst_base_sink_set_max_lateness (sink, g_value_get_int64 (value)); break; case PROP_QOS: gst_base_sink_set_qos_enabled (sink, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; }}static voidgst_base_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec){ GstBaseSink *sink = GST_BASE_SINK (object); switch (prop_id) { case PROP_PREROLL_QUEUE_LEN: GST_PAD_PREROLL_LOCK (sink->sinkpad); g_value_set_uint (value, sink->preroll_queue_max_len); GST_PAD_PREROLL_UNLOCK (sink->sinkpad); break; case PROP_SYNC: g_value_set_boolean (value, gst_base_sink_get_sync (sink)); break; case PROP_MAX_LATENESS: g_value_set_int64 (value, gst_base_sink_get_max_lateness (sink)); break; case PROP_QOS: g_value_set_boolean (value, gst_base_sink_is_qos_enabled (sink)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; }}static GstCaps *gst_base_sink_get_caps (GstBaseSink * sink){ return NULL;}static gbooleangst_base_sink_set_caps (GstBaseSink * sink, GstCaps * caps){ return TRUE;}static GstFlowReturngst_base_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf){ *buf = NULL; return GST_FLOW_OK;}/* with PREROLL_LOCK, STREAM_LOCK */static voidgst_base_sink_preroll_queue_flush (GstBaseSink * basesink, GstPad * pad){ GstMiniObject *obj; GST_DEBUG_OBJECT (basesink, "flushing queue %p", basesink); while ((obj = g_queue_pop_head (basesink->preroll_queue))) { GST_DEBUG_OBJECT (basesink, "popped %p", obj); gst_mini_object_unref (obj); } /* we can't have EOS anymore now */ basesink->eos = FALSE; basesink->eos_queued = FALSE; basesink->preroll_queued = 0; basesink->buffers_queued = 0; basesink->events_queued = 0; basesink->have_preroll = FALSE; /* and signal any waiters now */ GST_PAD_PREROLL_SIGNAL (pad);}/* with STREAM_LOCK, configures given segment with the event information. */static voidgst_base_sink_configure_segment (GstBaseSink * basesink, GstPad * pad, GstEvent * event, GstSegment * segment){ gboolean update; gdouble rate, arate; GstFormat format; gint64 start; gint64 stop; gint64 time; /* the newsegment event is needed to bring the buffer timestamps to the * stream time and to drop samples outside of the playback segment. */ gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time); /* The segment is protected with both the STREAM_LOCK and the OBJECT_LOCK. * We protect with the OBJECT_LOCK so that we can use the values to * safely answer a POSITION query. */ GST_OBJECT_LOCK (basesink); gst_segment_set_newsegment_full (segment, update, rate, arate, format, start, stop, time);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -