⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gstbasesrc.c

📁 GStreamer是一个开源的多媒体框架库。利用它
💻 C
📖 第 1 页 / 共 5 页
字号:
/* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> *               2000,2005 Wim Taymans <wim@fluendo.com> * * gstbasesrc.c: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//** * SECTION:gstbasesrc * @short_description: Base class for getrange based source elements * @see_also: #GstPushSrc, #GstBaseTransform, #GstBaseSink * * This is a generice base class for source elements. The following * types of sources are supported: * <itemizedlist> *   <listitem><para>random access sources like files</para></listitem> *   <listitem><para>seekable sources</para></listitem> *   <listitem><para>live sources</para></listitem> * </itemizedlist> * * <refsect2> * <para> * The source can be configured to operate in any #GstFormat with the * gst_base_src_set_format() method. The currently set format determines  * the format of the internal #GstSegment and any #GST_EVENT_NEWSEGMENT  * events. The default format for #GstBaseSrc is #GST_FORMAT_BYTES. * </para> * <para> * #GstBaseSrc always supports push mode scheduling. If the following * conditions are met, it also supports pull mode scheduling: * <itemizedlist> *   <listitem><para>The format is set to #GST_FORMAT_BYTES (default).</para> *   </listitem> *   <listitem><para>#GstBaseSrc::is_seekable returns %TRUE.</para> *   </listitem> * </itemizedlist> * </para> * <para> * Since 0.10.9, any #GstBaseSrc can enable pull based scheduling at any  * time by overriding #GstBaseSrc::check_get_range so that it returns %TRUE.  * </para> * <para> * If all the conditions are met for operating in pull mode, #GstBaseSrc is * automatically seekable in push mode as well. The following conditions must  * be met to make the element seekable in push mode when the format is not * #GST_FORMAT_BYTES: * <itemizedlist> *   <listitem><para> *     #GstBaseSrc::is_seekable returns %TRUE. *   </para></listitem> *   <listitem><para> *     #GstBaseSrc::query can convert all supported seek formats to the *     internal format as set with gst_base_src_set_format(). *   </para></listitem> *   <listitem><para> *     #GstBaseSrc::do_seek is implemented, performs the seek and returns %TRUE. *   </para></listitem> * </itemizedlist> * </para> * <para> * When the element does not meet the requirements to operate in pull mode, * the offset and length in the #GstBaseSrc::create method should be ignored. * It is recommended to subclass #GstPushSrc instead, in this situation. If the * element can operate in pull mode but only with specific offsets and * lengths, it is allowed to generate an error when the wrong values are passed * to the #GstBaseSrc::create function. * </para> * <para> * #GstBaseSrc has support for live sources. Live sources are sources that  * produce data at a fixed rate, such as audio or video capture devices. A  * typical live source also provides a clock to publish the rate at which  * they produce data. * Use gst_base_src_set_live() to activate the live source mode. * </para> * <para> * A live source does not produce data in the PAUSED state. This means that the  * #GstBaseSrc::create method will not be called in PAUSED but only in PLAYING. * To signal the pipeline that the element will not produce data, the return * value from the READY to PAUSED state will be #GST_STATE_CHANGE_NO_PREROLL. * </para> * <para> * A typical live source will timestamp the buffers it creates with the  * current stream time of the pipeline. This is one reason why a live source * can only produce data in the PLAYING state, when the clock is actually  * distributed and running. * </para> * <para> * Live sources that synchronize and block on the clock (and audio source, for * example) can since 0.10.12 use gst_base_src_wait_playing() when the ::create * function was interrupted by a state change to PAUSED. * </para> * <para> * The #GstBaseSrc::get_times method can be used to implement pseudo-live  * sources. The base source will wait for the specified stream time returned in  * #GstBaseSrc::get_times before pushing out the buffer.  * It only makes sense to implement the ::get_times function if the source is  * a live source. * </para> * <para> * There is only support in #GstBaseSrc for exactly one source pad, which  * should be named "src". A source implementation (subclass of #GstBaseSrc)  * should install a pad template in its base_init function, like so: * </para> * <para> * <programlisting> * static void * my_element_base_init (gpointer g_class) * { *   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); *   // srctemplate should be a #GstStaticPadTemplate with direction *   // #GST_PAD_SRC and name "src" *   gst_element_class_add_pad_template (gstelement_class, *       gst_static_pad_template_get (&amp;srctemplate)); *   // see #GstElementDetails *   gst_element_class_set_details (gstelement_class, &amp;details); * } * </programlisting> * </para> * <title>Controlled shutdown of live sources in applications</title> * <para> * Applications that record from a live source may want to stop recording * in a controlled way, so that the recording is stopped, but the data * already in the pipeline is processed to the end (remember that many live * sources would go on recording forever otherwise). For that to happen the * application needs to make the source stop recording and send an EOS * event down the pipeline. The application would then wait for an * EOS message posted on the pipeline's bus to know when all data has * been processed and the pipeline can safely be stopped. * </para> * <para> * Since GStreamer 0.10.3 an application may simply set the source * element to NULL or READY state to make it send an EOS event downstream. * The application should lock the state of the source afterwards, so that * shutting down the pipeline from PLAYING doesn't temporarily start up the * source element for a second time: * <programlisting> * ... * // stop recording * gst_element_set_state (audio_source, #GST_STATE_NULL); * gst_element_set_locked_state (audio_source, %TRUE); * ... * </programlisting> * Now the application should wait for an EOS message * to be posted on the pipeline's bus. Once it has received * an EOS message, it may safely shut down the entire pipeline: * <programlisting> * ... * // everything done - shut down pipeline * gst_element_set_state (pipeline, #GST_STATE_NULL); * gst_element_set_locked_state (audio_source, %FALSE); * ... * </programlisting> * </para> * <para> * Note that setting the source element to NULL or READY when the  * pipeline is in the PAUSED state may cause a deadlock since the streaming * thread might be blocked in PREROLL. * </para> * <para> * Last reviewed on 2006-09-27 (0.10.11) * </para> * </refsect2> */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include <stdlib.h>#include <string.h>#include "gstbasesrc.h"#include "gsttypefindhelper.h"#include <gst/gstmarshal.h>#include <gst/gst-i18n-lib.h>GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);#define GST_CAT_DEFAULT gst_base_src_debug#define GST_LIVE_GET_LOCK(elem)               (GST_BASE_SRC_CAST(elem)->live_lock)#define GST_LIVE_LOCK(elem)                   g_mutex_lock(GST_LIVE_GET_LOCK(elem))#define GST_LIVE_TRYLOCK(elem)                g_mutex_trylock(GST_LIVE_GET_LOCK(elem))#define GST_LIVE_UNLOCK(elem)                 g_mutex_unlock(GST_LIVE_GET_LOCK(elem))#define GST_LIVE_GET_COND(elem)               (GST_BASE_SRC_CAST(elem)->live_cond)#define GST_LIVE_WAIT(elem)                   g_cond_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem))#define GST_LIVE_TIMED_WAIT(elem, timeval)    g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem),\                                                                                timeval)#define GST_LIVE_SIGNAL(elem)                 g_cond_signal (GST_LIVE_GET_COND (elem));#define GST_LIVE_BROADCAST(elem)              g_cond_broadcast (GST_LIVE_GET_COND (elem));/* BaseSrc signals and args */enum{  /* FILL ME */  LAST_SIGNAL};#define DEFAULT_BLOCKSIZE       4096#define DEFAULT_NUM_BUFFERS     -1#define DEFAULT_TYPEFIND	FALSEenum{  PROP_0,  PROP_BLOCKSIZE,  PROP_NUM_BUFFERS,  PROP_TYPEFIND,};#define GST_BASE_SRC_GET_PRIVATE(obj)  \   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_SRC, GstBaseSrcPrivate))struct _GstBaseSrcPrivate{  gboolean last_sent_eos;       /* last thing we did was send an EOS (we set this                                 * to avoid the sending of two EOS in some cases) */  gboolean discont;  /* two segments to be sent in the streaming thread with STREAM_LOCK */  GstEvent *close_segment;  GstEvent *start_segment;};static GstElementClass *parent_class = NULL;static void gst_base_src_base_init (gpointer g_class);static void gst_base_src_class_init (GstBaseSrcClass * klass);static void gst_base_src_init (GstBaseSrc * src, gpointer g_class);static void gst_base_src_finalize (GObject * object);GTypegst_base_src_get_type (void){  static GType base_src_type = 0;  if (G_UNLIKELY (base_src_type == 0)) {    static const GTypeInfo base_src_info = {      sizeof (GstBaseSrcClass),      (GBaseInitFunc) gst_base_src_base_init,      NULL,      (GClassInitFunc) gst_base_src_class_init,      NULL,      NULL,      sizeof (GstBaseSrc),      0,      (GInstanceInitFunc) gst_base_src_init,    };    base_src_type = g_type_register_static (GST_TYPE_ELEMENT,        "GstBaseSrc", &base_src_info, G_TYPE_FLAG_ABSTRACT);  }  return base_src_type;}static GstCaps *gst_base_src_getcaps (GstPad * pad);static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);static void gst_base_src_fixate (GstPad * pad, GstCaps * caps);static gboolean gst_base_src_activate_push (GstPad * pad, gboolean active);static gboolean gst_base_src_activate_pull (GstPad * pad, gboolean active);static void gst_base_src_set_property (GObject * object, guint prop_id,    const GValue * value, GParamSpec * pspec);static void gst_base_src_get_property (GObject * object, guint prop_id,    GValue * value, GParamSpec * pspec);static gboolean gst_base_src_event_handler (GstPad * pad, GstEvent * event);static gboolean gst_base_src_send_event (GstElement * elem, GstEvent * event);static gboolean gst_base_src_default_event (GstBaseSrc * src, GstEvent * event);static const GstQueryType *gst_base_src_get_query_types (GstElement * element);static gboolean gst_base_src_query (GstPad * pad, GstQuery * query);static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);static gboolean gst_base_src_default_do_seek (GstBaseSrc * src,    GstSegment * segment);static gboolean gst_base_src_default_query (GstBaseSrc * src, GstQuery * query);static gboolean gst_base_src_default_prepare_seek_segment (GstBaseSrc * src,    GstEvent * event, GstSegment * segment);static gboolean gst_base_src_unlock (GstBaseSrc * basesrc);static gboolean gst_base_src_unlock_stop (GstBaseSrc * basesrc);static gboolean gst_base_src_start (GstBaseSrc * basesrc);static gboolean gst_base_src_stop (GstBaseSrc * basesrc);static GstStateChangeReturn gst_base_src_change_state (GstElement * element,    GstStateChange transition);static void gst_base_src_loop (GstPad * pad);static gboolean gst_base_src_pad_check_get_range (GstPad * pad);static gboolean gst_base_src_default_check_get_range (GstBaseSrc * bsrc);static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset,    guint length, GstBuffer ** buf);static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,    guint length, GstBuffer ** buf);static voidgst_base_src_base_init (gpointer g_class){  GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element");}static voidgst_base_src_class_init (GstBaseSrcClass * klass){  GObjectClass *gobject_class;  GstElementClass *gstelement_class;  gobject_class = G_OBJECT_CLASS (klass);  gstelement_class = GST_ELEMENT_CLASS (klass);  g_type_class_add_private (klass, sizeof (GstBaseSrcPrivate));  parent_class = g_type_class_peek_parent (klass);  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_src_finalize);  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_src_set_property);  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_src_get_property);  g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,      g_param_spec_ulong ("blocksize", "Block size",          "Size in bytes to read per buffer (0 = default)", 0, G_MAXULONG,          DEFAULT_BLOCKSIZE, G_PARAM_READWRITE));  g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,      g_param_spec_int ("num-buffers", "num-buffers",          "Number of buffers to output before sending EOS", -1, G_MAXINT,          DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE));  g_object_class_install_property (gobject_class, PROP_TYPEFIND,      g_param_spec_boolean ("typefind", "Typefind",          "Run typefind before negotiating", DEFAULT_TYPEFIND,          G_PARAM_READWRITE));  gstelement_class->change_state =      GST_DEBUG_FUNCPTR (gst_base_src_change_state);  gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_src_send_event);  gstelement_class->get_query_types =      GST_DEBUG_FUNCPTR (gst_base_src_get_query_types);  klass->negotiate = GST_DEBUG_FUNCPTR (gst_base_src_default_negotiate);  klass->event = GST_DEBUG_FUNCPTR (gst_base_src_default_event);  klass->do_seek = GST_DEBUG_FUNCPTR (gst_base_src_default_do_seek);  klass->query = GST_DEBUG_FUNCPTR (gst_base_src_default_query);  klass->check_get_range =      GST_DEBUG_FUNCPTR (gst_base_src_default_check_get_range);  klass->prepare_seek_segment =      GST_DEBUG_FUNCPTR (gst_base_src_default_prepare_seek_segment);}static voidgst_base_src_init (GstBaseSrc * basesrc, gpointer g_class){  GstPad *pad;  GstPadTemplate *pad_template;  basesrc->priv = GST_BASE_SRC_GET_PRIVATE (basesrc);  basesrc->is_live = FALSE;  basesrc->live_lock = g_mutex_new ();  basesrc->live_cond = g_cond_new ();  basesrc->num_buffers = DEFAULT_NUM_BUFFERS;  basesrc->num_buffers_left = -1;  basesrc->can_activate_push = TRUE;  basesrc->pad_mode = GST_ACTIVATE_NONE;  pad_template =      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");  g_return_if_fail (pad_template != NULL);  GST_DEBUG_OBJECT (basesrc, "creating src pad");  pad = gst_pad_new_from_template (pad_template, "src");  GST_DEBUG_OBJECT (basesrc, "setting functions on src pad");  gst_pad_set_activatepush_function (pad,      GST_DEBUG_FUNCPTR (gst_base_src_activate_push));  gst_pad_set_activatepull_function (pad,      GST_DEBUG_FUNCPTR (gst_base_src_activate_pull));  gst_pad_set_event_function (pad,      GST_DEBUG_FUNCPTR (gst_base_src_event_handler));  gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_query));  gst_pad_set_checkgetrange_function (pad,      GST_DEBUG_FUNCPTR (gst_base_src_pad_check_get_range));  gst_pad_set_getrange_function (pad,      GST_DEBUG_FUNCPTR (gst_base_src_pad_get_range));  gst_pad_set_getcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_getcaps));  gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_setcaps));  gst_pad_set_fixatecaps_function (pad,      GST_DEBUG_FUNCPTR (gst_base_src_fixate));  /* hold pointer to pad */  basesrc->srcpad = pad;  GST_DEBUG_OBJECT (basesrc, "adding src pad");  gst_element_add_pad (GST_ELEMENT (basesrc), pad);  basesrc->blocksize = DEFAULT_BLOCKSIZE;  basesrc->clock_id = NULL;  /* we operate in BYTES by default */  gst_base_src_set_format (basesrc, GST_FORMAT_BYTES);  basesrc->data.ABI.typefind = DEFAULT_TYPEFIND;  GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);  GST_DEBUG_OBJECT (basesrc, "init done");}static voidgst_base_src_finalize (GObject * object){  GstBaseSrc *basesrc;  GstEvent **event_p;  basesrc = GST_BASE_SRC (object);  g_mutex_free (basesrc->live_lock);  g_cond_free (basesrc->live_cond);  event_p = &basesrc->data.ABI.pending_seek;  gst_event_replace ((GstEvent **) event_p, NULL);  G_OBJECT_CLASS (parent_class)->finalize (object);}/** * gst_base_src_wait_playing: * @src: the src * * If the #GstBaseSrcClass::create method performs its own synchronisation against

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -