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

📄 gstbasesink.c

📁 gnash 在pc和嵌入式下开发需要的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* GStreamer * Copyright (C) 2005-2007 Wim Taymans <wim.taymans@gmail.com> * * gstbasesink.c: Base class for sink elements * * 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:gstbasesink * @short_description: Base class for sink elements * @see_also: #GstBaseTransform, #GstBaseSource * * #GstBaseSink is the base class for sink elements in GStreamer, such as * xvimagesink or filesink. It is a layer on top of #GstElement that provides a * simplified interface to plugin writers. #GstBaseSink handles many details * for you, for example: preroll, clock synchronization, state changes, * activation in push or pull mode, and queries. * * In most cases, when writing sink elements, there is no need to implement * class methods from #GstElement or to set functions on pads, because the * #GstBaseSink infrastructure should be sufficient. * * #GstBaseSink provides support for exactly one sink pad, which should be * named "sink". A sink implementation (subclass of #GstBaseSink) should * install a pad template in its base_init function, like so: * <programlisting> * static void * my_element_base_init (gpointer g_class) * { *   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); *    *   // sinktemplate should be a #GstStaticPadTemplate with direction *   // #GST_PAD_SINK and name "sink" *   gst_element_class_add_pad_template (gstelement_class, *       gst_static_pad_template_get (&amp;sinktemplate)); *   // see #GstElementDetails *   gst_element_class_set_details (gstelement_class, &amp;details); * } * </programlisting> * * #GstBaseSink will handle the prerolling correctly. This means that it will * return #GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first * buffer arrives in this element. The base class will call the * #GstBaseSink::preroll vmethod with this preroll buffer and will then commit * the state change to the next asynchronously pending state. * * When the element is set to PLAYING, #GstBaseSink will synchronise on the * clock using the times returned from ::get_times. If this function returns * #GST_CLOCK_TIME_NONE for the start time, no synchronisation will be done. * Synchronisation can be disabled entirely by setting the object "sync" * property to %FALSE. * * After synchronisation the virtual method #GstBaseSink::render will be called. * Subclasses should minimally implement this method. * * Since 0.10.3 subclasses that synchronise on the clock in the ::render method * are supported as well. These classes typically receive a buffer in the render * method and can then potentially block on the clock while rendering. A typical * example is an audiosink. Since 0.10.11 these subclasses can use * gst_base_sink_wait_preroll() to perform the blocking wait. * * Upon receiving the EOS event in the PLAYING state, #GstBaseSink will wait * for the clock to reach the time indicated by the stop time of the last * ::get_times call before posting an EOS message. When the element receives * EOS in PAUSED, preroll completes, the event is queued and an EOS message is * posted when going to PLAYING. * * #GstBaseSink will internally use the #GST_EVENT_NEWSEGMENT events to schedule * synchronisation and clipping of buffers. Buffers that fall completely outside * of the current segment are dropped. Buffers that fall partially in the * segment are rendered (and prerolled). Subclasses should do any subbuffer * clipping themselves when needed. * * #GstBaseSink will by default report the current playback position in * #GST_FORMAT_TIME based on the current clock time and segment information. * If no clock has been set on the element, the query will be forwarded * upstream. * * The ::set_caps function will be called when the subclass should configure * itself to process a specific media type. * * The ::start and ::stop virtual methods will be called when resources should * be allocated. Any ::preroll, ::render  and ::set_caps function will be * called between the ::start and ::stop calls. * * The ::event virtual method will be called when an event is received by * #GstBaseSink. Normally this method should only be overriden by very specific * elements (such as file sinks) which need to handle the newsegment event * specially. * * #GstBaseSink provides an overridable ::buffer_alloc function that can be * used by sinks that want to do reverse negotiation or to provide * custom buffers (hardware buffers for example) to upstream elements. * * The ::unlock method is called when the elements should unblock any blocking * operations they perform in the ::render method. This is mostly useful when * the ::render method performs a blocking write on a file descriptor, for * example. * * The max-lateness property affects how the sink deals with buffers that * arrive too late in the sink. A buffer arrives too late in the sink when * the presentation time (as a combination of the last segment, buffer * timestamp and element base_time) plus the duration is before the current * time of the clock. * If the frame is later than max-lateness, the sink will drop the buffer * without calling the render method. * This feature is disabled if sync is disabled, the ::get-times method does * not return a valid start time or max-lateness is set to -1 (the default). * Subclasses can use gst_base_sink_set_max_lateness() to configure the * max-lateness value. * * The qos property will enable the quality-of-service features of the basesink * which gather statistics about the real-time performance of the clock * synchronisation. For each buffer received in the sink, statistics are * gathered and a QOS event is sent upstream with these numbers. This * information can then be used by upstream elements to reduce their processing * rate, for example. * * Since 0.10.15 the async property can be used to instruct the sink to never * perform an ASYNC state change. This feature is mostly usable when dealing * with non-synchronized streams or sparse streams. * * Last reviewed on 2007-08-29 (0.10.15) */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "gstbasesink.h"#include <gst/gstmarshal.h>#include <gst/gst_private.h>#include <gst/gst-i18n-lib.h>GST_DEBUG_CATEGORY_STATIC (gst_base_sink_debug);#define GST_CAT_DEFAULT gst_base_sink_debug#define GST_BASE_SINK_GET_PRIVATE(obj)  \   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_SINK, GstBaseSinkPrivate))/* FIXME, some stuff in ABI.data and other in Private... * Make up your mind please. */struct _GstBaseSinkPrivate{  gint qos_enabled;             /* ATOMIC */  gboolean async_enabled;  GstClockTimeDiff ts_offset;  /* start, stop of current buffer, stream time, used to report position */  GstClockTime current_sstart;  GstClockTime current_sstop;  /* start, stop and jitter of current buffer, running time */  GstClockTime current_rstart;  GstClockTime current_rstop;  GstClockTimeDiff current_jitter;  /* EOS sync time in running time */  GstClockTime eos_rtime;  /* last buffer that arrived in time, running time */  GstClockTime last_in_time;  /* when the last buffer left the sink, running time */  GstClockTime last_left;  /* running averages go here these are done on running time */  GstClockTime avg_pt;  GstClockTime avg_duration;  gdouble avg_rate;  /* these are done on system time. avg_jitter and avg_render are   * compared to eachother to see if the rendering time takes a   * huge amount of the processing, If so we are flooded with   * buffers. */  GstClockTime last_left_systime;  GstClockTime avg_jitter;  GTimeVal start, stop;  GstClockTime avg_render;  /* number of rendered and dropped frames */  guint64 rendered;  guint64 dropped;  /* latency stuff */  GstClockTime latency;  /* if we already commited the state */  gboolean commited;  /* when we received EOS */  gboolean received_eos;  /* when we are prerolled and able to report latency */  gboolean have_latency;  /* the last buffer we prerolled or rendered. Useful for making snapshots */  GstBuffer *last_buffer;};#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))/* generic running average, this has a neutral window size */#define UPDATE_RUNNING_AVG(avg,val)   DO_RUNNING_AVG(avg,val,8)/* the windows for these running averages are experimentally obtained. * possitive values get averaged more while negative values use a small * window so we can react faster to badness. */#define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16)#define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4)/* BaseSink properties */#define DEFAULT_SIZE 1024#define DEFAULT_CAN_ACTIVATE_PULL FALSE /* fixme: enable me */#define DEFAULT_CAN_ACTIVATE_PUSH TRUE#define DEFAULT_PREROLL_QUEUE_LEN	0#define DEFAULT_SYNC			TRUE#define DEFAULT_MAX_LATENESS		-1#define DEFAULT_QOS			FALSE#define DEFAULT_ASYNC			TRUE#define DEFAULT_TS_OFFSET		0enum{  PROP_0,  PROP_PREROLL_QUEUE_LEN,  PROP_SYNC,  PROP_MAX_LATENESS,  PROP_QOS,  PROP_ASYNC,  PROP_TS_OFFSET,  PROP_LAST_BUFFER,  PROP_LAST};static GstElementClass *parent_class = NULL;static void gst_base_sink_base_init (gpointer g_class);static void gst_base_sink_class_init (GstBaseSinkClass * klass);static void gst_base_sink_init (GstBaseSink * trans, gpointer g_class);static void gst_base_sink_finalize (GObject * object);GTypegst_base_sink_get_type (void){  static GType base_sink_type = 0;  if (G_UNLIKELY (base_sink_type == 0)) {    static const GTypeInfo base_sink_info = {      sizeof (GstBaseSinkClass),      (GBaseInitFunc) gst_base_sink_base_init,      NULL,      (GClassInitFunc) gst_base_sink_class_init,      NULL,      NULL,      sizeof (GstBaseSink),      0,      (GInstanceInitFunc) gst_base_sink_init,    };    base_sink_type = g_type_register_static (GST_TYPE_ELEMENT,        "GstBaseSink", &base_sink_info, G_TYPE_FLAG_ABSTRACT);  }  return base_sink_type;}static void gst_base_sink_set_property (GObject * object, guint prop_id,    const GValue * value, GParamSpec * pspec);static void gst_base_sink_get_property (GObject * object, guint prop_id,    GValue * value, GParamSpec * pspec);static gboolean gst_base_sink_send_event (GstElement * element,    GstEvent * event);static gboolean gst_base_sink_query (GstElement * element, GstQuery * query);static GstCaps *gst_base_sink_get_caps (GstBaseSink * sink);static gboolean gst_base_sink_set_caps (GstBaseSink * sink, GstCaps * caps);static GstFlowReturn gst_base_sink_buffer_alloc (GstBaseSink * sink,    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);static void gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,    GstClockTime * start, GstClockTime * end);static gboolean gst_base_sink_set_flushing (GstBaseSink * basesink,    GstPad * pad, gboolean flushing);static gboolean gst_base_sink_default_activate_pull (GstBaseSink * basesink,    gboolean active);static GstStateChangeReturn gst_base_sink_change_state (GstElement * element,    GstStateChange transition);static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);static void gst_base_sink_loop (GstPad * pad);static gboolean gst_base_sink_pad_activate (GstPad * pad);static gboolean gst_base_sink_pad_activate_push (GstPad * pad, gboolean active);static gboolean gst_base_sink_pad_activate_pull (GstPad * pad, gboolean active);static gboolean gst_base_sink_event (GstPad * pad, GstEvent * event);static gboolean gst_base_sink_peer_query (GstBaseSink * sink, GstQuery * query);/* check if an object was too late */static gboolean gst_base_sink_is_too_late (GstBaseSink * basesink,    GstMiniObject * obj, GstClockTime start, GstClockTime stop,    GstClockReturn status, GstClockTimeDiff jitter);static voidgst_base_sink_base_init (gpointer g_class){  GST_DEBUG_CATEGORY_INIT (gst_base_sink_debug, "basesink", 0,      "basesink element");}static voidgst_base_sink_class_init (GstBaseSinkClass * 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 (GstBaseSinkPrivate));  parent_class = g_type_class_peek_parent (klass);  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_sink_finalize);  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_sink_set_property);  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_sink_get_property);  /* FIXME, this next value should be configured using an event from the   * upstream element, ie, the BUFFER_SIZE event. */  g_object_class_install_property (gobject_class, PROP_PREROLL_QUEUE_LEN,      g_param_spec_uint ("preroll-queue-len", "Preroll queue length",          "Number of buffers to queue during preroll", 0, G_MAXUINT,          DEFAULT_PREROLL_QUEUE_LEN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));  g_object_class_install_property (gobject_class, PROP_SYNC,      g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC,          G_PARAM_READWRITE));  g_object_class_install_property (gobject_class, PROP_MAX_LATENESS,      g_param_spec_int64 ("max-lateness", "Max Lateness",          "Maximum number of nanoseconds that a buffer can be late before it "          "is dropped (-1 unlimited)", -1, G_MAXINT64, DEFAULT_MAX_LATENESS,          G_PARAM_READWRITE));  g_object_class_install_property (gobject_class, PROP_QOS,      g_param_spec_boolean ("qos", "Qos",          "Generate Quality-of-Service events upstream", DEFAULT_QOS,          G_PARAM_READWRITE));  /**   * GstBaseSink:async   *   * If set to #TRUE, the basesink will perform asynchronous state changes.   * When set to #FALSE, the sink will not signal the parent when it prerolls.   * Use this option when dealing with sparse streams or when synchronisation is   * not required.   *   * Since: 0.10.15   */  g_object_class_install_property (gobject_class, PROP_ASYNC,      g_param_spec_boolean ("async", "Async",          "Go asynchronously to PAUSED", DEFAULT_ASYNC, G_PARAM_READWRITE));  /**   * GstBaseSink:ts-offset   *   * Controls the final synchronisation, a negative value will render the buffer   * earlier while a positive value delays playback. This property can be    * used to fix synchronisation in bad files.   *   * Since: 0.10.15   */  g_object_class_install_property (gobject_class, PROP_TS_OFFSET,      g_param_spec_int64 ("ts-offset", "TS Offset",          "Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64,          DEFAULT_TS_OFFSET, G_PARAM_READWRITE));  /**   * GstBaseSink:last-buffer   *   * The last buffer that arrived in the sink and was used for preroll or for   * rendering. This property can be used to generate thumbnails.   *   * Since: 0.10.15   */  g_object_class_install_property (gobject_class, PROP_LAST_BUFFER,      gst_param_spec_mini_object ("last-buffer", "Last Buffer",          "The last buffer received in the sink", GST_TYPE_BUFFER,          G_PARAM_READABLE));  gstelement_class->change_state =      GST_DEBUG_FUNCPTR (gst_base_sink_change_state);  gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_sink_send_event);  gstelement_class->query = GST_DEBUG_FUNCPTR (gst_base_sink_query);  klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_sink_get_caps);  klass->set_caps = GST_DEBUG_FUNCPTR (gst_base_sink_set_caps);  klass->buffer_alloc = GST_DEBUG_FUNCPTR (gst_base_sink_buffer_alloc);  klass->get_times = GST_DEBUG_FUNCPTR (gst_base_sink_get_times);  klass->activate_pull =      GST_DEBUG_FUNCPTR (gst_base_sink_default_activate_pull);}static GstCaps *gst_base_sink_pad_getcaps (GstPad * pad){  GstBaseSinkClass *bclass;  GstBaseSink *bsink;  GstCaps *caps = NULL;  bsink = GST_BASE_SINK (gst_pad_get_parent (pad));  bclass = GST_BASE_SINK_GET_CLASS (bsink);  if (bclass->get_caps)    caps = bclass->get_caps (bsink);  if (caps == NULL) {    GstPadTemplate *pad_template;    pad_template =        gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");    if (pad_template != NULL) {      caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));    }

⌨️ 快捷键说明

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