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

📄 gstbasesrc.c

📁 gnash 在pc和嵌入式下开发需要的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        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_LOG_OBJECT (src, "report latency: live %d, min %" GST_TIME_FORMAT          ", max %" GST_TIME_FORMAT, live, GST_TIME_ARGS (min),          GST_TIME_ARGS (max));      gst_query_set_latency (query, live, min, max);      break;    }    case GST_QUERY_JITTER:    case GST_QUERY_RATE:    default:      res = FALSE;      break;  }  GST_DEBUG_OBJECT (src, "query %s returns %d", GST_QUERY_TYPE_NAME (query),      res);  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;  }  if (cur_type != GST_SEEK_TYPE_NONE) {    /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */    res =        gst_pad_query_convert (src->srcpad, seek_format, cur, &dest_format,        &cur);    cur_type = GST_SEEK_TYPE_SET;  }  if (res && stop_type != GST_SEEK_TYPE_NONE) {    /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */    res =        gst_pad_query_convert (src->srcpad, seek_format, stop, &dest_format,        &stop);    stop_type = GST_SEEK_TYPE_SET;  }  /* And finally, configure our output segment in the desired format */  gst_segment_set_seek (segment, rate, dest_format, flags, cur_type, cur,      stop_type, stop, &update);  if (!res)    goto no_format;  return res;no_format:  {    GST_DEBUG_OBJECT (src, "undefined format given, seek aborted.");    return FALSE;  }}static gbooleangst_base_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,    GstSegment * seeksegment){  GstBaseSrcClass *bclass;  gboolean result = FALSE;  bclass = GST_BASE_SRC_GET_CLASS (src);  if (bclass->prepare_seek_segment)    result = bclass->prepare_seek_segment (src, event, seeksegment);  return result;}/* this code implements the seeking. It is a good example * handling all cases. * * A seek updates the currently configured segment.start * and segment.stop values based on the SEEK_TYPE. If the * segment.start value is updated, a seek to this new position * should be performed. * * The seek can only be executed when we are not currently * streaming any data, to make sure that this is the case, we * acquire the STREAM_LOCK which is taken when we are in the * _loop() function or when a getrange() is called. Normally * we will not receive a seek if we are operating in pull mode * though. When we operate as a live source we might block on the live * cond, which does not release the STREAM_LOCK. Therefore we will try * to grab the LIVE_LOCK instead of the STREAM_LOCK to make sure it is * safe to perform the seek. * * When we are in the loop() function, we might be in the middle * of pushing a buffer, which might block in a sink. To make sure * that the push gets unblocked we push out a FLUSH_START event. * Our loop function will get a WRONG_STATE return value from * the push and will pause, effectively releasing the STREAM_LOCK. * * For a non-flushing seek, we pause the task, which might eventually * release the STREAM_LOCK. We say eventually because when the sink * blocks on the sample we might wait a very long time until the sink * unblocks the sample. In any case we acquire the STREAM_LOCK and * can continue the seek. A non-flushing seek is normally done in a  * running pipeline to perform seamless playback, this means that the sink is * PLAYING and will return from its chain function. * In the case of a non-flushing seek we need to make sure that the * data we output after the seek is continuous with the previous data, * this is because a non-flushing seek does not reset the running-time * to 0. We do this by closing the currently running segment, ie. sending * a new_segment event with the stop position set to the last processed  * position. * * After updating the segment.start/stop values, we prepare for * streaming again. We push out a FLUSH_STOP to make the peer pad * accept data again and we start our task again. * * A segment seek posts a message on the bus saying that the playback * of the segment started. We store the segment flag internally because * when we reach the segment.stop we have to post a segment.done * instead of EOS when doing a segment seek. *//* FIXME (0.11), we have the unlock gboolean here because most current  * implementations (fdsrc, -base/gst/tcp/, ...) unconditionally unlock, even when * the streaming thread isn't running, resulting in bogus unlocks later when it  * starts. This is fixed by adding unlock_stop, but we should still avoid unlocking * unnecessarily for backwards compatibility. Ergo, the unlock variable stays * until 0.11 */static gbooleangst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock){  gboolean res = TRUE;  gdouble rate;  GstFormat seek_format, dest_format;  GstSeekFlags flags;  GstSeekType cur_type, stop_type;  gint64 cur, stop;  gboolean flush, playing;  gboolean update;  gboolean relative_seek = FALSE;  gboolean seekseg_configured = FALSE;  GstSegment seeksegment;  GST_DEBUG_OBJECT (src, "doing seek");  dest_format = src->segment.format;  if (event) {    gst_event_parse_seek (event, &rate, &seek_format, &flags,        &cur_type, &cur, &stop_type, &stop);    relative_seek = SEEK_TYPE_IS_RELATIVE (cur_type) ||        SEEK_TYPE_IS_RELATIVE (stop_type);    if (dest_format != seek_format && !relative_seek) {      /* If we have an ABSOLUTE position (SEEK_SET only), we can convert it       * here before taking the stream lock, otherwise we must convert it later,       * once we have the stream lock and can read the current position */      gst_segment_init (&seeksegment, dest_format);      if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment))        goto prepare_failed;      seekseg_configured = TRUE;    }    flush = flags & GST_SEEK_FLAG_FLUSH;  } else {    flush = FALSE;  }  /* send flush start */  if (flush)    gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());  else    gst_pad_pause_task (src->srcpad);  /* unblock streaming thread. */  gst_base_src_set_flushing (src, TRUE, FALSE, unlock, &playing);  /* grab streaming lock, this should eventually be possible, either   * because the task is paused, our streaming thread stopped    * or because our peer is flushing. */  GST_PAD_STREAM_LOCK (src->srcpad);  gst_base_src_set_flushing (src, FALSE, playing, unlock, NULL);  /* If we configured the seeksegment above, don't overwrite it now. Otherwise   * copy the current segment info into the temp segment that we can actually   * attempt the seek with. We only update the real segment if the seek suceeds. */  if (!seekseg_configured) {    memcpy (&seeksegment, &src->segment, sizeof (GstSegment));    /* now configure the final seek segment */    if (event) {      if (src->segment.format != seek_format) {        /* OK, here's where we give the subclass a chance to convert the relative         * seek into an absolute one in the processing format. We set up any         * absolute seek above, before taking the stream lock. */        if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment)) {          GST_DEBUG_OBJECT (src, "Preparing the seek failed after flushing. "              "Aborting seek");          res = FALSE;        }      } else {        /* The seek format matches our processing format, no need to ask the         * the subclass to configure the segment. */        gst_segment_set_seek (&seeksegment, rate, seek_format, flags,            cur_type, cur, stop_type, stop, &update);      }    }    /* Else, no seek event passed, so we're just (re)starting the        current segment. */  }  if (res) {    GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT        " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,        seeksegment.start, seeksegment.stop, seeksegment.last_stop);    /* do the seek, segment.last_stop contains the new position. */    res = gst_base_src_do_seek (src, &seeksegment);  }  /* and prepare to continue streaming */  if (flush) {    /* send flush stop, peer will accept data and events again. We     * are not yet providing data as we still have the STREAM_LOCK. */    gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());  } else if (res && src->data.ABI.running) {    /* we are running the current segment and doing a non-flushing seek,      * close the segment first based on the last_stop. */    GST_DEBUG_OBJECT (src, "closing running segment %" G_GINT64_FORMAT        " to %" G_GINT64_FORMAT, src->segment.start, src->segment.last_stop);    /* queue the segment for sending in the stream thread */    if (src->priv->close_segment)      gst_event_unref (src->priv->close_segment);    src->priv->close_segment =        gst_event_new_new_segment_full (TRUE,        src->segment.rate, src->segment.applied_rate, src->segment.format,        src->segment.start, src->segment.last_stop, src->segment.time);  }  /* The subclass must have converted the segment to the processing format    * by now */  if (res && seeksegment.format != dest_format) {    GST_DEBUG_OBJECT (src, "Subclass failed to prepare a seek segment "        "in the correct format. Aborting seek.");    res = FALSE;  }  /* if successfull seek, we update our real segment and push   * out the new segment. */  if (res) {    memcpy (&src->segment, &seeksegment, sizeof (GstSegment));    if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {      gst_element_post_message (GST_ELEMENT (src),          gst_message_new_segment_start (GST_OBJECT (src),              src->segment.format, src->segment.last_stop));    }    /* for deriving a stop position for the playback segment form the seek     * segment, we must take the duration when the stop is not set */    if ((stop = src->segment.stop) == -1)      stop = src->segment.duration;    GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT        " to %" G_GINT64_FORMAT, src->segment.start, stop);    /* now replace the old segment so that we send it in the stream thread the     * next time it is scheduled. */    if (src->priv->start_segment)      gst_event_unref (src->priv->start_segment);    src->priv->start_segment =        gst_event_new_new_segment_full (FALSE,        src->segment.rate, src->segment.applied_rate, src->segment.format,        src->segment.last_stop, stop, src->segment.time);  }  src->priv->discont = TRUE;  src->data.ABI.running = TRUE;  /* and restart the task in case it got paused explicitely or by   * the FLUSH_START event we pushed out. */  gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,      src->srcpad);  /* and release the lock again so we can continue streaming */  GST_PAD_STREAM_UNLOCK (src->srcpad);  return res;  /* ERROR */prepare_failed:  GST_DEBUG_OBJECT (src, "Preparing the seek failed before flushing. "      "Aborting seek");  return FALSE;}static const GstQueryType *gst_base_src_get_query_types (GstElement * element){  static const GstQueryType query_types[] = {    GST_QUERY_DURATION,    GST_QUERY_POSITION,    GST_QUERY_SEEKING,    GST_QUERY_SEGMENT,    GST_QUERY_FORMATS,    GST_QUERY_LATENCY,    GST_QUERY_JITTER,    GST_QUERY_RATE,    GST_QUERY_CONVERT,    0  };  return query_types;}/* all events send to this element directly. This is mainly done from the * application. */static gbooleangst_base_src_send_event (GstElement * element, GstEvent * event){  GstBaseSrc *src;  gboolean result = FALSE;  src = GST_BASE_SRC (element);  switch (GST_EVENT_TYPE (event)) {      /* bidirectional events */    case GST_EVENT_FLUSH_START:    case GST_EVENT_FLUSH_STOP:      /* sending random flushes downstream can break stuff,

⌨️ 快捷键说明

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