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

📄 gstbasesink.c

📁 gnash 在pc和嵌入式下开发需要的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        sstart = sstop = priv->current_sstop;        rstart = rstop = priv->eos_rtime;        *do_sync = rstart != -1;        GST_DEBUG_OBJECT (basesink, "sync times for EOS %" GST_TIME_FORMAT,            GST_TIME_ARGS (rstart));        goto done;        /* other events do not need syncing */        /* FIXME, maybe NEWSEGMENT might need synchronisation         * since the POSITION query depends on accumulated times and         * we cannot accumulate the current segment before the previous         * one completed.         */      default:        return FALSE;    }  }  /* else do buffer sync code */  buffer = GST_BUFFER_CAST (obj);  bclass = GST_BASE_SINK_GET_CLASS (basesink);  /* just get the times to see if we need syncing */  if (bclass->get_times)    bclass->get_times (basesink, buffer, &start, &stop);  if (start == -1) {    gst_base_sink_get_times (basesink, buffer, &start, &stop);    *do_sync = FALSE;  } else {    *do_sync = TRUE;  }  GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT      ", stop: %" GST_TIME_FORMAT ", do_sync %d", GST_TIME_ARGS (start),      GST_TIME_ARGS (stop), *do_sync);  /* collect segment and format for code clarity */  format = segment->format;  /* no timestamp clipping if we did not * get a TIME segment format */  if (G_UNLIKELY (format != GST_FORMAT_TIME)) {    cstart = start;    cstop = stop;    /* do running and stream time in TIME format */    format = GST_FORMAT_TIME;    goto do_times;  }  /* clip */  if (G_UNLIKELY (!gst_segment_clip (segment, GST_FORMAT_TIME,              (gint64) start, (gint64) stop, &cstart, &cstop)))    goto out_of_segment;  if (G_UNLIKELY (start != cstart || stop != cstop)) {    GST_DEBUG_OBJECT (basesink, "clipped to: start %" GST_TIME_FORMAT        ", stop: %" GST_TIME_FORMAT, GST_TIME_ARGS (cstart),        GST_TIME_ARGS (cstop));  }  /* set last stop position */  gst_segment_set_last_stop (segment, GST_FORMAT_TIME, cstop);do_times:  /* this can produce wrong values if we accumulated non-TIME segments. If this happens,   * upstream is behaving very badly */  sstart = gst_segment_to_stream_time (segment, format, cstart);  sstop = gst_segment_to_stream_time (segment, format, cstop);  rstart = gst_segment_to_running_time (segment, format, cstart);  rstop = gst_segment_to_running_time (segment, format, cstop);done:  /* save times */  *rsstart = sstart;  *rsstop = sstop;  *rrstart = rstart;  *rrstop = rstop;  /* buffers and EOS always need syncing and preroll */  return TRUE;  /* special cases */out_of_segment:  {    /* should not happen since we clip them in the chain function already,      * we return FALSE so that we don't try to sync on it. */    GST_ELEMENT_WARNING (basesink, STREAM, FAILED,        (NULL), ("unexpected buffer out of segment found."));    GST_LOG_OBJECT (basesink, "buffer skipped, not in segment");    return FALSE;  }}/* with STREAM_LOCK, PREROLL_LOCK * * Waits for the clock to reach @time. If @time is not valid, no * synchronisation is done and BADTIME is returned.  * If synchronisation is disabled in the element or there is no * clock, no synchronisation is done and BADTIME is returned. * * Else a blocking wait is performed on the clock. We save the ClockID * so we can unlock the entry at any time. While we are blocking, we  * release the PREROLL_LOCK so that other threads can interrupt the entry. * * @time is expressed in running time. */static GstClockReturngst_base_sink_wait_clock (GstBaseSink * basesink, GstClockTime time,    GstClockTimeDiff * jitter){  GstClockID id;  GstClockReturn ret;  GstClock *clock;  GstClockTimeDiff ts_offset;  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time)))    goto invalid_time;  GST_OBJECT_LOCK (basesink);  if (G_UNLIKELY (!basesink->sync))    goto no_sync;  if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (basesink)) == NULL))    goto no_clock;  /* add base time and latency */  time += GST_ELEMENT_CAST (basesink)->base_time;  time += basesink->priv->latency;  /* apply offset, be carefull for underflows */  ts_offset = basesink->priv->ts_offset;  if (ts_offset < 0) {    ts_offset = -ts_offset;    if (ts_offset < time)      time -= ts_offset;    else      time = 0;  } else    time += ts_offset;  id = gst_clock_new_single_shot_id (clock, time);  GST_OBJECT_UNLOCK (basesink);  basesink->clock_id = id;  /* release the preroll lock while waiting */  GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);  ret = gst_clock_id_wait (id, jitter);  GST_PAD_PREROLL_LOCK (basesink->sinkpad);  gst_clock_id_unref (id);  basesink->clock_id = NULL;  return ret;  /* no syncing needed */invalid_time:  {    GST_DEBUG_OBJECT (basesink, "time not valid, no sync needed");    return GST_CLOCK_BADTIME;  }no_sync:  {    GST_DEBUG_OBJECT (basesink, "sync disabled");    GST_OBJECT_UNLOCK (basesink);    return GST_CLOCK_BADTIME;  }no_clock:  {    GST_DEBUG_OBJECT (basesink, "no clock, can't sync");    GST_OBJECT_UNLOCK (basesink);    return GST_CLOCK_BADTIME;  }}/** * gst_base_sink_wait_preroll: * @sink: the sink * * If the #GstBaseSinkClass::render method performs its own synchronisation against * the clock it must unblock when going from PLAYING to the PAUSED state and call * this method before continuing to render 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.11 * * Returns: #GST_FLOW_OK if the preroll completed and processing can * continue. Any other return value should be returned from the render vmethod. */GstFlowReturngst_base_sink_wait_preroll (GstBaseSink * sink){  sink->have_preroll = TRUE;  GST_DEBUG_OBJECT (sink, "waiting in preroll for flush or PLAYING");  /* block until the state changes, or we get a flush, or something */  GST_PAD_PREROLL_WAIT (sink->sinkpad);  sink->have_preroll = FALSE;  if (G_UNLIKELY (sink->flushing))    goto stopping;  GST_DEBUG_OBJECT (sink, "continue after preroll");  return GST_FLOW_OK;  /* ERRORS */stopping:  {    GST_DEBUG_OBJECT (sink, "preroll interrupted");    return GST_FLOW_WRONG_STATE;  }}/** * gst_base_sink_wait_eos: * @sink: the sink * @time: the running_time to be reached * @jitter: the jitter to be filled with time diff (can be NULL) * * This function will block until @time is reached. It is usually called by * subclasses that use their own internal synchronisation but want to let the * EOS be handled by the base class. * * This function should only be called with the PREROLL_LOCK held, like when * receiving an EOS event in the ::event vmethod. * * Since 0.10.15 * * Returns: #GstFlowReturn */GstFlowReturngst_base_sink_wait_eos (GstBaseSink * sink, GstClockTime time,    GstClockTimeDiff * jitter){  GstClockReturn status;  GstFlowReturn ret;  do {    GST_DEBUG_OBJECT (sink, "checking preroll");    /* first wait for the playing state before we can continue */    if (G_UNLIKELY (sink->need_preroll)) {      ret = gst_base_sink_wait_preroll (sink);      if (ret != GST_FLOW_OK)        goto flushing;    }    /* preroll done, we can sync since we are in PLAYING now. */    GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %"        GST_TIME_FORMAT, GST_TIME_ARGS (time));    /* wait for the clock, this can be interrupted because we got shut down or      * we PAUSED. */    status = gst_base_sink_wait_clock (sink, time, jitter);    GST_DEBUG_OBJECT (sink, "clock returned %d", status);    /* invalid time, no clock or sync disabled, just continue then */    if (status == GST_CLOCK_BADTIME)      break;    /* waiting could have been interrupted and we can be flushing now */    if (G_UNLIKELY (sink->flushing))      goto flushing;    /* retry if we got unscheduled, which means we did not reach the timeout     * yet. if some other error occures, we continue. */  } while (status == GST_CLOCK_UNSCHEDULED);  GST_DEBUG_OBJECT (sink, "end of stream");  return GST_FLOW_OK;  /* ERRORS */flushing:  {    GST_DEBUG_OBJECT (sink, "we are flushing");    return GST_FLOW_WRONG_STATE;  }}/* with STREAM_LOCK, PREROLL_LOCK * * Make sure we are in PLAYING and synchronize an object to the clock. * * If we need preroll, we are not in PLAYING. We try to commit the state * if needed and then block if we still are not PLAYING. * * We start waiting on the clock in PLAYING. If we got interrupted, we * immediatly try to re-preroll. * * Some objects do not need synchronisation (most events) and so this function * immediatly returns GST_FLOW_OK. * * for objects that arrive later than max-lateness to be synchronized to the  * clock have the @late boolean set to TRUE. * * This function keeps a running average of the jitter (the diff between the * clock time and the requested sync time). The jitter is negative for * objects that arrive in time and positive for late buffers. * * does not take ownership of obj. */static GstFlowReturngst_base_sink_do_sync (GstBaseSink * basesink, GstPad * pad,    GstMiniObject * obj, gboolean * late){  GstClockTimeDiff jitter;  gboolean syncable;  GstClockReturn status = GST_CLOCK_OK;  GstClockTime rstart, rstop, sstart, sstop;  gboolean do_sync;  GstBaseSinkPrivate *priv;  priv = basesink->priv;  sstart = sstop = rstart = rstop = -1;  do_sync = TRUE;  priv->current_rstart = -1;  /* get timing information for this object against the render segment */  syncable = gst_base_sink_get_sync_times (basesink, obj,      &sstart, &sstop, &rstart, &rstop, &do_sync, &basesink->segment);  /* a syncable object needs to participate in preroll and   * clocking. All buffers and EOS are syncable. */  if (G_UNLIKELY (!syncable))    goto not_syncable;  /* store timing info for current object */  priv->current_rstart = rstart;  priv->current_rstop = (rstop != -1 ? rstop : rstart);  /* save sync time for eos when the previous object needed sync */  priv->eos_rtime = (do_sync ? priv->current_rstop : -1);again:  /* first do preroll, this makes sure we commit our state   * to PAUSED and can continue to PLAYING. We cannot perform   * any clock sync in PAUSED because there is no clock.    */  while (G_UNLIKELY (basesink->need_preroll)) {    GST_DEBUG_OBJECT (basesink, "prerolling object %p", obj);    if (G_LIKELY (basesink->playing_async)) {      /* commit state */      if (G_UNLIKELY (!gst_base_sink_commit_state (basesink)))        goto stopping;    }    /* need to recheck here because the commit state could have     * made us not need the preroll anymore */    if (G_LIKELY (basesink->need_preroll)) {      /* block until the state changes, or we get a flush, or something */      if (gst_base_sink_wait_preroll (basesink) != GST_FLOW_OK)        goto flushing;    }  }  /* After rendering we store the position of the last buffer so that we can use   * it to report the position. We need to take the lock here. */  GST_OBJECT_LOCK (basesink);  priv->current_sstart = sstart;  priv->current_sstop = (sstop != -1 ? sstop : sstart);  GST_OBJECT_UNLOCK (basesink);  if (!do_sync)    goto done;  /* preroll done, we can sync since we are in PLAYING now. */  GST_DEBUG_OBJECT (basesink, "possibly waiting for clock to reach %"      GST_TIME_FORMAT, GST_TIME_ARGS (rstart));  /* this function will return immediatly if start == -1, no clock   * or sync is disabled with GST_CLOCK_BADTIME. */  status = gst_base_sink_wait_clock (basesink, rstart, &jitter);  GST_DEBUG_OBJECT (basesink, "clock returned %d", status);  /* invalid time, no clock or sync disabled, just render */  if (status == GST_CLOCK_BADTIME)    goto done;  /* waiting could have been interrupted and we can be flushing now */  if (G_UNLIKELY (basesink->flushing))    goto flushing;  /* check for unlocked by a state change, we are not flushing so   * we can try to preroll on the current buffer. */  if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {    GST_DEBUG_OBJECT (basesink, "unscheduled, waiting some more");    goto again;  }  /* successful syncing done, record observation */  priv->current_jitter = jitter;  /* check if the object should be dropped */  *late = gst_base_sink_is_too_late (basesink, obj, rstart, rstop,      status, jitter);done:  return GST_FLOW_OK;  /* ERRORS */not_syncable:  {    GST_DEBUG_OBJECT (basesink, "non syncable object %p", obj);    return GST_FLOW_OK;  }flushing:  {    GST_DEBUG_OBJECT (basesink, "we are flushing");    return GST_FLOW_WRONG_STATE;  }stopping:  {    GST_DEBUG_OBJECT (basesink, "stopping while commiting state");    return GST_FLOW_WRONG_STATE;  }}static gbooleangst_base_sink_send_qos (GstBaseSink * basesink,    gdouble proportion, GstClockTime time, GstClockTimeDiff diff){  GstEvent *event;  gboolean res;  /* generate Quality-of-Service event */  GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,      "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"      GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (time));

⌨️ 快捷键说明

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