📄 gstbasesrc.c
字号:
* the clock it must unblock when going from PLAYING to the PAUSED state and call * this method before continuing to produce the remaining data. * * This function will block until a state change to PLAYING happens (in which * case this function returns #GST_FLOW_OK) or the processing must be stopped due * to a state change to READY or a FLUSH event (in which case this function * returns #GST_FLOW_WRONG_STATE). * * Since: 0.10.12 * * Returns: #GST_FLOW_OK if @src is PLAYING and processing can * continue. Any other return value should be returned from the create vmethod. */GstFlowReturngst_base_src_wait_playing (GstBaseSrc * src){ /* block until the state changes, or we get a flush, or something */ GST_LIVE_LOCK (src); if (src->is_live) { while (G_UNLIKELY (!src->live_running)) { GST_DEBUG ("live source signal waiting"); GST_LIVE_SIGNAL (src); GST_DEBUG ("live source waiting for running state"); GST_LIVE_WAIT (src); GST_DEBUG ("live source unlocked"); } /* FIXME, use another variable to signal stopping so that we don't * have to grab another lock. */ GST_OBJECT_LOCK (src->srcpad); if (G_UNLIKELY (GST_PAD_IS_FLUSHING (src->srcpad))) goto flushing; GST_OBJECT_UNLOCK (src->srcpad); } GST_LIVE_UNLOCK (src); return GST_FLOW_OK; /* ERRORS */flushing: { GST_DEBUG_OBJECT (src, "pad is flushing"); GST_OBJECT_UNLOCK (src->srcpad); GST_LIVE_UNLOCK (src); return GST_FLOW_WRONG_STATE; }}/** * gst_base_src_set_live: * @src: base source instance * @live: new live-mode * * If the element listens to a live source, @live should * be set to %TRUE. * * A live source will not produce data in the PAUSED state and * will therefore not be able to participate in the PREROLL phase * of a pipeline. To signal this fact to the application and the * pipeline, the state change return value of the live source will * be GST_STATE_CHANGE_NO_PREROLL. */voidgst_base_src_set_live (GstBaseSrc * src, gboolean live){ GST_LIVE_LOCK (src); src->is_live = live; GST_LIVE_UNLOCK (src);}/** * gst_base_src_is_live: * @src: base source instance * * Check if an element is in live mode. * * Returns: %TRUE if element is in live mode. */gbooleangst_base_src_is_live (GstBaseSrc * src){ gboolean result; GST_LIVE_LOCK (src); result = src->is_live; GST_LIVE_UNLOCK (src); return result;}/** * gst_base_src_set_format: * @src: base source instance * @format: the format to use * * Sets the default format of the source. This will be the format used * for sending NEW_SEGMENT events and for performing seeks. * * If a format of GST_FORMAT_BYTES is set, the element will be able to * operate in pull mode if the #GstBaseSrc::is_seekable returns TRUE. * * @Since: 0.10.1 */voidgst_base_src_set_format (GstBaseSrc * src, GstFormat format){ gst_segment_init (&src->segment, format);}/** * gst_base_src_query_latency: * @src: the source * @live: if the source is live * @min_latency: the min latency of the source * @max_latency: the max latency of the source * * Query the source for the latency parameters. @live will be TRUE when @src is * configured as a live source. @min_latency will be set as the latency between * calling the create function and the timestamp on the resulting buffer. * @max_latency is always the undefined value of -1. * * This function is mostly used by subclasses. * * Returns: TRUE if the query succeeded. * * Since: 0.10.13 */gbooleangst_base_src_query_latency (GstBaseSrc * src, gboolean * live, GstClockTime * min_latency, GstClockTime * max_latency){ GST_LIVE_LOCK (src); if (live) *live = src->is_live; if (min_latency) *min_latency = 0; if (max_latency) *max_latency = -1; GST_LIVE_UNLOCK (src); return TRUE;}static gbooleangst_base_src_setcaps (GstPad * pad, GstCaps * caps){ GstBaseSrcClass *bclass; GstBaseSrc *bsrc; gboolean res = TRUE; bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad)); bclass = GST_BASE_SRC_GET_CLASS (bsrc); if (bclass->set_caps) res = bclass->set_caps (bsrc, caps); return res;}static GstCaps *gst_base_src_getcaps (GstPad * pad){ GstBaseSrcClass *bclass; GstBaseSrc *bsrc; GstCaps *caps = NULL; bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad)); bclass = GST_BASE_SRC_GET_CLASS (bsrc); if (bclass->get_caps) caps = bclass->get_caps (bsrc); if (caps == NULL) { GstPadTemplate *pad_template; pad_template = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src"); if (pad_template != NULL) { caps = gst_caps_ref (gst_pad_template_get_caps (pad_template)); } } return caps;}static voidgst_base_src_fixate (GstPad * pad, GstCaps * caps){ GstBaseSrcClass *bclass; GstBaseSrc *bsrc; bsrc = GST_BASE_SRC (gst_pad_get_parent (pad)); bclass = GST_BASE_SRC_GET_CLASS (bsrc); if (bclass->fixate) bclass->fixate (bsrc, caps); gst_object_unref (bsrc);}static gbooleangst_base_src_default_query (GstBaseSrc * src, GstQuery * query){ gboolean res; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat format; gst_query_parse_position (query, &format, NULL); switch (format) { case GST_FORMAT_PERCENT: { gint64 percent; gint64 position; gint64 duration; position = src->segment.last_stop; duration = src->segment.duration; if (position != -1 && duration != -1) { if (position < duration) percent = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, position, duration); else percent = GST_FORMAT_PERCENT_MAX; } else percent = -1; gst_query_set_position (query, GST_FORMAT_PERCENT, percent); res = TRUE; break; } default: { gint64 position; position = src->segment.last_stop; if (position != -1) { /* convert to requested format */ res = gst_pad_query_convert (src->srcpad, src->segment.format, position, &format, &position); } else res = TRUE; gst_query_set_position (query, format, position); break; } } break; } case GST_QUERY_DURATION: { GstFormat format; gst_query_parse_duration (query, &format, NULL); switch (format) { case GST_FORMAT_PERCENT: gst_query_set_duration (query, GST_FORMAT_PERCENT, GST_FORMAT_PERCENT_MAX); res = TRUE; break; default: { gint64 duration; duration = src->segment.duration; if (duration != -1) { /* convert to requested format */ res = gst_pad_query_convert (src->srcpad, src->segment.format, duration, &format, &duration); } else { res = TRUE; } gst_query_set_duration (query, format, duration); break; } } break; } case GST_QUERY_SEEKING: { gst_query_set_seeking (query, src->segment.format, src->seekable, 0, src->segment.duration); res = TRUE; break; } case GST_QUERY_SEGMENT: { gint64 start, stop; /* no end segment configured, current duration then */ if ((stop = src->segment.stop) == -1) stop = src->segment.duration; start = src->segment.start; /* adjust to stream time */ if (src->segment.time != -1) { start -= src->segment.time; if (stop != -1) stop -= src->segment.time; } gst_query_set_segment (query, src->segment.rate, src->segment.format, start, stop); res = TRUE; break; } case GST_QUERY_FORMATS: { gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES, GST_FORMAT_PERCENT); res = TRUE; break; } case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); /* we can only convert between equal formats... */ if (src_fmt == dest_fmt) { dest_val = src_val; res = TRUE; } else res = FALSE; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } case GST_QUERY_LATENCY: { GstClockTime min, max; gboolean live; /* Subclasses should override and implement something usefull */ res = gst_base_src_query_latency (src, &live, &min, &max); gst_query_set_latency (query, live, min, max); break; } case GST_QUERY_JITTER: case GST_QUERY_RATE: default: res = FALSE; break; } return res;}static gbooleangst_base_src_query (GstPad * pad, GstQuery * query){ GstBaseSrc *src; GstBaseSrcClass *bclass; gboolean result = FALSE; src = GST_BASE_SRC (gst_pad_get_parent (pad)); bclass = GST_BASE_SRC_GET_CLASS (src); if (bclass->query) result = bclass->query (src, query); else result = gst_pad_query_default (pad, query); gst_object_unref (src); return result;}static gbooleangst_base_src_default_do_seek (GstBaseSrc * src, GstSegment * segment){ gboolean res = TRUE; /* update our offset if the start/stop position was updated */ if (segment->format == GST_FORMAT_BYTES) { segment->last_stop = segment->start; segment->time = segment->start; } else if (segment->start == 0) { /* seek to start, we can implement a default for this. */ segment->last_stop = 0; segment->time = 0; res = TRUE; } else res = FALSE; return res;}static gbooleangst_base_src_do_seek (GstBaseSrc * src, GstSegment * segment){ GstBaseSrcClass *bclass; gboolean result = FALSE; bclass = GST_BASE_SRC_GET_CLASS (src); if (bclass->do_seek) result = bclass->do_seek (src, segment); return result;}#define SEEK_TYPE_IS_RELATIVE(t) (((t) != GST_SEEK_TYPE_NONE) && ((t) != GST_SEEK_TYPE_SET))static gbooleangst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event, GstSegment * segment){ /* By default, we try one of 2 things: * - For absolute seek positions, convert the requested position to our * configured processing format and place it in the output segment \ * - For relative seek positions, convert our current (input) values to the * seek format, adjust by the relative seek offset and then convert back to * the processing format */ GstSeekType cur_type, stop_type; gint64 cur, stop; GstSeekFlags flags; GstFormat seek_format, dest_format; gdouble rate; gboolean update; gboolean res = TRUE; gst_event_parse_seek (event, &rate, &seek_format, &flags, &cur_type, &cur, &stop_type, &stop); dest_format = segment->format; if (seek_format == dest_format) { gst_segment_set_seek (segment, rate, seek_format, flags, cur_type, cur, stop_type, stop, &update); return TRUE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -