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

📄 gstbasesink.c

📁 gnash 在pc和嵌入式下开发需要的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  event = gst_event_new_qos (proportion, diff, time);  /* send upstream */  res = gst_pad_push_event (basesink->sinkpad, event);  return res;}static voidgst_base_sink_perform_qos (GstBaseSink * sink, gboolean dropped){  GstBaseSinkPrivate *priv;  GstClockTime start, stop;  GstClockTimeDiff jitter;  GstClockTime pt, entered, left;  GstClockTime duration;  gdouble rate;  priv = sink->priv;  start = priv->current_rstart;  /* if Quality-of-Service disabled, do nothing */  if (!g_atomic_int_get (&priv->qos_enabled) || start == -1)    return;  stop = priv->current_rstop;  jitter = priv->current_jitter;  /* this is the time the buffer entered the sink */  entered = start + jitter;  /* this is the time the buffer left the sink */  left = start + (jitter < 0 ? 0 : jitter);  /* calculate duration of the buffer */  if (stop != -1)    duration = stop - start;  else    duration = -1;  /* if we have the time when the last buffer left us, calculate   * processing time */  if (priv->last_left != -1) {    if (entered > priv->last_left) {      pt = entered - priv->last_left;    } else {      pt = 0;    }  } else {    pt = priv->avg_pt;  }  GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink, "start: %" GST_TIME_FORMAT      ", entered %" GST_TIME_FORMAT ", left %" GST_TIME_FORMAT ", pt: %"      GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ",jitter %"      G_GINT64_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (entered),      GST_TIME_ARGS (left), GST_TIME_ARGS (pt), GST_TIME_ARGS (duration),      jitter);  GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink, "avg_duration: %" GST_TIME_FORMAT      ", avg_pt: %" GST_TIME_FORMAT ", avg_rate: %g",      GST_TIME_ARGS (priv->avg_duration), GST_TIME_ARGS (priv->avg_pt),      priv->avg_rate);  /* collect running averages. for first observations, we copy the   * values */  if (priv->avg_duration == -1)    priv->avg_duration = duration;  else    priv->avg_duration = UPDATE_RUNNING_AVG (priv->avg_duration, duration);  if (priv->avg_pt == -1)    priv->avg_pt = pt;  else    priv->avg_pt = UPDATE_RUNNING_AVG (priv->avg_pt, pt);  if (priv->avg_duration != 0)    rate =        gst_guint64_to_gdouble (priv->avg_pt) /        gst_guint64_to_gdouble (priv->avg_duration);  else    rate = 0.0;  if (priv->last_left != -1) {    if (dropped || priv->avg_rate < 0.0) {      priv->avg_rate = rate;    } else {      if (rate > 1.0)        priv->avg_rate = UPDATE_RUNNING_AVG_N (priv->avg_rate, rate);      else        priv->avg_rate = UPDATE_RUNNING_AVG_P (priv->avg_rate, rate);    }  }  GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink,      "updated: avg_duration: %" GST_TIME_FORMAT ", avg_pt: %" GST_TIME_FORMAT      ", avg_rate: %g", GST_TIME_ARGS (priv->avg_duration),      GST_TIME_ARGS (priv->avg_pt), priv->avg_rate);  /* if we have a valid rate, start sending QoS messages */  if (priv->avg_rate >= 0.0) {    gst_base_sink_send_qos (sink, priv->avg_rate, priv->current_rstart,        priv->current_jitter);  }  /* record when this buffer will leave us */  priv->last_left = left;}/* reset all qos measuring */static voidgst_base_sink_reset_qos (GstBaseSink * sink){  GstBaseSinkPrivate *priv;  priv = sink->priv;  priv->last_in_time = -1;  priv->last_left = -1;  priv->avg_duration = -1;  priv->avg_pt = -1;  priv->avg_rate = -1.0;  priv->avg_render = -1;  priv->rendered = 0;  priv->dropped = 0;}/* Checks if the object was scheduled too late. * * start/stop contain the raw timestamp start and stop values * of the object. * * status and jitter contain the return values from the clock wait. * * returns TRUE if the buffer was too late. */static gbooleangst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,    GstClockTime start, GstClockTime stop,    GstClockReturn status, GstClockTimeDiff jitter){  gboolean late;  gint64 max_lateness;  GstBaseSinkPrivate *priv;  priv = basesink->priv;  late = FALSE;  /* only for objects that were too late */  if (G_LIKELY (status != GST_CLOCK_EARLY))    goto in_time;  max_lateness = basesink->abidata.ABI.max_lateness;  /* check if frame dropping is enabled */  if (max_lateness == -1)    goto no_drop;  /* only check for buffers */  if (G_UNLIKELY (!GST_IS_BUFFER (obj)))    goto not_buffer;  /* can't do check if we don't have a timestamp */  if (G_UNLIKELY (start == -1))    goto no_timestamp;  /* we can add a valid stop time */  if (stop != -1)    max_lateness += stop;  else    max_lateness += start;  /* if the jitter bigger than duration and lateness we are too late */  if ((late = start + jitter > max_lateness)) {    GST_DEBUG_OBJECT (basesink, "buffer is too late %" GST_TIME_FORMAT        " > %" GST_TIME_FORMAT, GST_TIME_ARGS (start + jitter),        GST_TIME_ARGS (max_lateness));    /* !!emergency!!, if we did not receive anything valid for more than a      * second, render it anyway so the user sees something */    if (priv->last_in_time && start - priv->last_in_time > GST_SECOND) {      late = FALSE;      GST_DEBUG_OBJECT (basesink,          "**emergency** last buffer at %" GST_TIME_FORMAT " > GST_SECOND",          GST_TIME_ARGS (priv->last_in_time));    }  }done:  if (!late) {    priv->last_in_time = start;  }  return late;  /* all is fine */in_time:  {    GST_DEBUG_OBJECT (basesink, "object was scheduled in time");    goto done;  }no_drop:  {    GST_DEBUG_OBJECT (basesink, "frame dropping disabled");    goto done;  }not_buffer:  {    GST_DEBUG_OBJECT (basesink, "object is not a buffer");    return FALSE;  }no_timestamp:  {    GST_DEBUG_OBJECT (basesink, "buffer has no timestamp");    return FALSE;  }}static voidgst_base_sink_do_render_stats (GstBaseSink * basesink, gboolean start){  GstBaseSinkPrivate *priv;  priv = basesink->priv;  if (start) {    g_get_current_time (&priv->start);  } else {    GstClockTime elapsed;    g_get_current_time (&priv->stop);    elapsed =        GST_TIMEVAL_TO_TIME (priv->stop) - GST_TIMEVAL_TO_TIME (priv->start);    if (priv->avg_render == -1)      priv->avg_render = elapsed;    else      priv->avg_render = UPDATE_RUNNING_AVG (priv->avg_render, elapsed);    GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,        "avg_render: %" GST_TIME_FORMAT, GST_TIME_ARGS (priv->avg_render));  }}/* with STREAM_LOCK, PREROLL_LOCK, * * Synchronize the object on the clock and then render it. * * takes ownership of obj. */static GstFlowReturngst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad,    GstMiniObject * obj){  GstFlowReturn ret = GST_FLOW_OK;  GstBaseSinkClass *bclass;  gboolean late = FALSE;  GstBaseSinkPrivate *priv;  priv = basesink->priv;  /* synchronize this object, non syncable objects return OK   * immediatly. */  ret = gst_base_sink_do_sync (basesink, pad, obj, &late);  if (G_UNLIKELY (ret != GST_FLOW_OK))    goto sync_failed;  /* and now render, event or buffer. */  if (G_LIKELY (GST_IS_BUFFER (obj))) {    GstBuffer *buf;    /* drop late buffers unconditionally, let's hope it's unlikely */    if (G_UNLIKELY (late))      goto dropped;    buf = GST_BUFFER_CAST (obj);    gst_base_sink_set_last_buffer (basesink, buf);    bclass = GST_BASE_SINK_GET_CLASS (basesink);    if (G_LIKELY (bclass->render)) {      gint do_qos;      /* read once, to get same value before and after */      do_qos = g_atomic_int_get (&priv->qos_enabled);      GST_DEBUG_OBJECT (basesink, "rendering buffer %p", obj);      /* record rendering time for QoS and stats */      if (do_qos)        gst_base_sink_do_render_stats (basesink, TRUE);      ret = bclass->render (basesink, buf);      priv->rendered++;      if (do_qos)        gst_base_sink_do_render_stats (basesink, FALSE);    }  } else {    GstEvent *event = GST_EVENT_CAST (obj);    gboolean event_res = TRUE;    GstEventType type;    bclass = GST_BASE_SINK_GET_CLASS (basesink);    type = GST_EVENT_TYPE (event);    GST_DEBUG_OBJECT (basesink, "rendering event %p, type %s", obj,        gst_event_type_get_name (type));    if (bclass->event)      event_res = bclass->event (basesink, event);    if (G_LIKELY (event_res)) {      switch (type) {        case GST_EVENT_EOS:          /* the EOS event is completely handled so we mark           * ourselves as being in the EOS state. eos is also            * protected by the object lock so we can read it when            * answering the POSITION query. */          GST_OBJECT_LOCK (basesink);          basesink->eos = TRUE;          GST_OBJECT_UNLOCK (basesink);          /* ok, now we can post the message */          GST_DEBUG_OBJECT (basesink, "Now posting EOS");          gst_element_post_message (GST_ELEMENT_CAST (basesink),              gst_message_new_eos (GST_OBJECT_CAST (basesink)));          break;        case GST_EVENT_NEWSEGMENT:          /* configure the segment */          gst_base_sink_configure_segment (basesink, pad, event,              &basesink->segment);          break;        default:          break;      }    }  }done:  gst_base_sink_perform_qos (basesink, late);  GST_DEBUG_OBJECT (basesink, "object unref after render %p", obj);  gst_mini_object_unref (obj);  return ret;  /* ERRORS */sync_failed:  {    GST_DEBUG_OBJECT (basesink, "do_sync returned %s", gst_flow_get_name (ret));    goto done;  }dropped:  {    priv->dropped++;    GST_DEBUG_OBJECT (basesink, "buffer late, dropping");    goto done;  }}/* with STREAM_LOCK, PREROLL_LOCK * * Perform preroll on the given object. For buffers this means  * calling the preroll subclass method.  * If that succeeds, the state will be commited. * * function does not take ownership of obj. */static GstFlowReturngst_base_sink_preroll_object (GstBaseSink * basesink, GstPad * pad,    GstMiniObject * obj){  GstFlowReturn ret;  GST_DEBUG_OBJECT (basesink, "do preroll %p", obj);  /* if it's a buffer, we need to call the preroll method */  if (G_LIKELY (GST_IS_BUFFER (obj))) {    GstBaseSinkClass *bclass;    GstBuffer *buf;    GstClockTime timestamp;    buf = GST_BUFFER_CAST (obj);    timestamp = GST_BUFFER_TIMESTAMP (buf);    GST_DEBUG_OBJECT (basesink, "preroll buffer %" GST_TIME_FORMAT,        GST_TIME_ARGS (timestamp));    gst_base_sink_set_last_buffer (basesink, buf);    bclass = GST_BASE_SINK_GET_CLASS (basesink);    if (bclass->preroll)      if ((ret = bclass->preroll (basesink, buf)) != GST_FLOW_OK)        goto preroll_failed;  }  /* commit state */  if (G_LIKELY (basesink->playing_async)) {    if (G_UNLIKELY (!gst_base_sink_commit_state (basesink)))      goto stopping;  }  return GST_FLOW_OK;  /* ERRORS */preroll_failed:  {    GST_DEBUG_OBJECT (basesink, "preroll failed, abort state");    gst_element_abort_state (GST_ELEMENT_CAST (basesink));    return ret;  }stopping:  {    GST_DEBUG_OBJECT (basesink, "stopping while commiting state");    return GST_FLOW_WRONG_STATE;  }}/* with STREAM_LOCK, PREROLL_LOCK  * * Queue an object for rendering. * The first prerollable object queued will complete the preroll. If the * preroll queue if filled, we render all the objects in the queue. * * This function takes ownership of the object. */static GstFlowReturngst_base_sink_queue_object_unlocked (GstB

⌨️ 快捷键说明

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