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

📄 gstbasetransform.c

📁 gnash 在pc和嵌入式下开发需要的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  }done:  if (out_caps)    gst_caps_unref (out_caps);  trans->delay_configure = FALSE;  return ret;}/* Given @caps calcultate the size of one unit. * * For video caps, this is the size of one frame (and thus one buffer). * For audio caps, this is the size of one sample. * * These values are cached since they do not change and the calculation * potentially involves parsing caps and other expensive stuff. * * We have two cache locations to store the size, one for the source caps * and one for the sink caps. * * this function returns FALSE if no size could be calculated. */static gbooleangst_base_transform_get_unit_size (GstBaseTransform * trans, GstCaps * caps,    guint * size){  gboolean res = FALSE;  GstBaseTransformClass *bclass;  /* see if we have the result cached */  if (trans->cache_caps1 == caps) {    *size = trans->cache_caps1_size;    GST_DEBUG_OBJECT (trans, "returned %d from first cache", *size);    return TRUE;  }  if (trans->cache_caps2 == caps) {    *size = trans->cache_caps2_size;    GST_DEBUG_OBJECT (trans, "returned %d from second cached", *size);    return TRUE;  }  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);  if (bclass->get_unit_size) {    res = bclass->get_unit_size (trans, caps, size);    GST_DEBUG_OBJECT (trans, "caps %" GST_PTR_FORMAT        ") has unit size %d, result %s", caps, *size, res ? "TRUE" : "FALSE");    if (res) {      /* and cache the values */      if (trans->cache_caps1 == NULL) {        gst_caps_replace (&trans->cache_caps1, caps);        trans->cache_caps1_size = *size;        GST_DEBUG_OBJECT (trans, "caching %d in first cache", *size);      } else if (trans->cache_caps2 == NULL) {        gst_caps_replace (&trans->cache_caps2, caps);        trans->cache_caps2_size = *size;        GST_DEBUG_OBJECT (trans, "caching %d in second cache", *size);      } else {        GST_DEBUG_OBJECT (trans, "no free spot to cache unit_size");      }    }  } else {    GST_DEBUG_OBJECT (trans, "Sub-class does not implement get_unit_size");  }  return res;}/* your upstream peer wants to send you a buffer * that buffer has the given offset, size and caps * you're requested to allocate a buffer */static GstFlowReturngst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,    GstCaps * caps, GstBuffer ** buf){  GstBaseTransform *trans;  GstFlowReturn res;  guint new_size;  gboolean issinkcaps = TRUE;  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));  /* we cannot run this when we are transforming data and as such doing    * another negotiation in the transform method. */  g_mutex_lock (trans->transform_lock);  *buf = NULL;  GST_DEBUG_OBJECT (trans, "allocating a buffer of size %d ...", size);  if (offset == GST_BUFFER_OFFSET_NONE)    GST_DEBUG_OBJECT (trans, "... and offset NONE");  else    GST_DEBUG_OBJECT (trans, "... and offset %" G_GUINT64_FORMAT, offset);  /* if have_same_caps was previously set to TRUE we need to double check if it   * hasn't changed */  if (trans->have_same_caps) {    GstCaps *sinkcaps;    GST_OBJECT_LOCK (trans->sinkpad);    sinkcaps = GST_PAD_CAPS (trans->sinkpad);    issinkcaps = sinkcaps && (gst_caps_is_equal (sinkcaps, caps));    GST_OBJECT_UNLOCK (trans->sinkpad);  }  /* before any buffers are pushed, have_same_caps is TRUE; allocating can trigger   * a renegotiation and change that to FALSE */  /* bilboed: This seems wrong, from all debug logs, have_same_caps is   * initialized to FALSE */  /* checking against trans->have_same_caps is not enough !! It should also   *  check to see if the requested caps are equal to the sink caps */  if (trans->have_same_caps && issinkcaps) {    /* request a buffer with the same caps */    GST_DEBUG_OBJECT (trans, "requesting buffer with same caps, size %d", size);    res =        gst_pad_alloc_buffer_and_set_caps (trans->srcpad, offset, size, caps,        buf);  } else {    /* if we are configured, request a buffer with the src caps */    GstCaps *srccaps;    GstCaps *sinkcaps;    gboolean configured;    /* take lock, peek if the caps are ok */    GST_OBJECT_LOCK (trans->sinkpad);    sinkcaps = GST_PAD_CAPS (trans->sinkpad);    configured = (sinkcaps == NULL || gst_caps_is_equal (sinkcaps, caps));    GST_OBJECT_UNLOCK (trans->sinkpad);    if (!configured)      goto not_configured;    /* take lock on srcpad to grab the caps, caps can change when pushing a     * buffer. */    GST_OBJECT_LOCK (trans->srcpad);    if ((srccaps = GST_PAD_CAPS (trans->srcpad)))      gst_caps_ref (srccaps);    GST_OBJECT_UNLOCK (trans->srcpad);    if (!srccaps)      goto not_configured;    GST_DEBUG_OBJECT (trans, "calling transform_size");    if (!gst_base_transform_transform_size (trans,            GST_PAD_DIRECTION (pad), caps, size, srccaps, &new_size)) {      gst_caps_unref (srccaps);      goto unknown_size;    }    res =        gst_pad_alloc_buffer_and_set_caps (trans->srcpad, offset, new_size,        srccaps, buf);    gst_caps_unref (srccaps);  }  if (res == GST_FLOW_OK && !trans->have_same_caps) {    /* note that we might have had same caps before, but calling the       alloc_buffer caused setcaps to switch us out of in_place -- in any case       the alloc_buffer served to transmit caps information but we can't use the       buffer. fall through and allocate a buffer corresponding to our sink       caps, if any */    GstCaps *sinkcaps;    GstCaps *srccaps;    GST_OBJECT_LOCK (trans->sinkpad);    if ((sinkcaps = GST_PAD_CAPS (trans->sinkpad)))      gst_caps_ref (sinkcaps);    GST_OBJECT_UNLOCK (trans->sinkpad);    if (!sinkcaps)      goto not_configured;    GST_OBJECT_LOCK (trans->srcpad);    if ((srccaps = GST_PAD_CAPS (trans->srcpad)))      gst_caps_ref (srccaps);    GST_OBJECT_UNLOCK (trans->srcpad);    if (!srccaps) {      gst_caps_unref (sinkcaps);      goto not_configured;    }    if (!gst_base_transform_transform_size (trans,            GST_PAD_DIRECTION (trans->srcpad), srccaps, GST_BUFFER_SIZE (*buf),            sinkcaps, &new_size)) {      gst_caps_unref (srccaps);      gst_caps_unref (sinkcaps);      goto unknown_size;    }    /* don't need the caps anymore now */    gst_caps_unref (srccaps);    gst_buffer_unref (*buf);    *buf = gst_buffer_new_and_alloc (new_size);    GST_BUFFER_OFFSET (*buf) = offset;    /* set caps, gives away the ref */    GST_BUFFER_CAPS (*buf) = sinkcaps;    res = GST_FLOW_OK;  }done:  g_mutex_unlock (trans->transform_lock);  gst_object_unref (trans);  return res;not_configured:  {    /* let the default allocator handle it... */    GST_DEBUG_OBJECT (trans, "not configured");    gst_buffer_replace (buf, NULL);    if (trans->passthrough) {      /* ...by calling alloc_buffer without setting caps on the src pad, which       * will force negotiation in the chain function. */      res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);    } else {      /* ...by letting the default handler create a buffer */      res = GST_FLOW_OK;    }    goto done;  }unknown_size:  {    /* let the default allocator handle it... */    GST_DEBUG_OBJECT (trans, "unknown size");    gst_buffer_replace (buf, NULL);    if (trans->passthrough) {      /* ...by calling alloc_buffer without setting caps on the src pad, which       * will force negotiation in the chain function. */      res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);    } else {      /* ...by letting the default handler create a buffer */      res = GST_FLOW_OK;    }    goto done;  }}static gbooleangst_base_transform_sink_event (GstPad * pad, GstEvent * event){  GstBaseTransform *trans;  GstBaseTransformClass *bclass;  gboolean ret = TRUE;  gboolean forward = TRUE;  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);  if (bclass->event)    forward = bclass->event (trans, event);  /* FIXME, do this in the default event handler so the subclass can do   * something different. */  if (forward)    ret = gst_pad_push_event (trans->srcpad, event);  gst_object_unref (trans);  return ret;}static gbooleangst_base_transform_sink_eventfunc (GstBaseTransform * trans, GstEvent * event){  switch (GST_EVENT_TYPE (event)) {    case GST_EVENT_FLUSH_START:      break;    case GST_EVENT_FLUSH_STOP:      GST_OBJECT_LOCK (trans);      /* reset QoS parameters */      trans->priv->proportion = 1.0;      trans->priv->earliest_time = -1;      trans->priv->discont = FALSE;      GST_OBJECT_UNLOCK (trans);      /* we need new segment info after the flush. */      trans->have_newsegment = FALSE;      gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);      break;    case GST_EVENT_EOS:      break;    case GST_EVENT_TAG:      break;    case GST_EVENT_NEWSEGMENT:    {      GstFormat format;      gdouble rate, arate;      gint64 start, stop, time;      gboolean update;      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,          &start, &stop, &time);      trans->have_newsegment = TRUE;      gst_segment_set_newsegment_full (&trans->segment, update, rate, arate,          format, start, stop, time);      if (format == GST_FORMAT_TIME) {        GST_DEBUG_OBJECT (trans, "received TIME NEW_SEGMENT %" GST_TIME_FORMAT            " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT            ", accum %" GST_TIME_FORMAT,            GST_TIME_ARGS (trans->segment.start),            GST_TIME_ARGS (trans->segment.stop),            GST_TIME_ARGS (trans->segment.time),            GST_TIME_ARGS (trans->segment.accum));      } else {        GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" G_GINT64_FORMAT            " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT            ", accum %" G_GINT64_FORMAT,            trans->segment.start, trans->segment.stop,            trans->segment.time, trans->segment.accum);      }      break;    }    default:      break;  }  return TRUE;}static gbooleangst_base_transform_src_event (GstPad * pad, GstEvent * event){  GstBaseTransform *trans;  GstBaseTransformClass *bclass;  gboolean ret = TRUE;  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);  if (bclass->src_event)    ret = bclass->src_event (trans, event);  gst_object_unref (trans);  return ret;}static gbooleangst_base_transform_src_eventfunc (GstBaseTransform * trans, GstEvent * event){  gboolean ret;  switch (GST_EVENT_TYPE (event)) {    case GST_EVENT_SEEK:      break;    case GST_EVENT_NAVIGATION:      break;    case GST_EVENT_QOS:    {      gdouble proportion;      GstClockTimeDiff diff;      GstClockTime timestamp;      gst_event_parse_qos (event, &proportion, &diff, &timestamp);      gst_base_transform_update_qos (trans, proportion, diff, timestamp);      break;    }    default:      break;  }  ret = gst_pad_push_event (trans->sinkpad, event);  return ret;}static GstFlowReturngst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,    GstBuffer ** outbuf){  GstBaseTransformClass *bclass;  GstFlowReturn ret = GST_FLOW_OK;  guint out_size;  gboolean want_in_place;  GstClockTime qostime;  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);  if (GST_BUFFER_OFFSET_IS_VALID (inbuf))    GST_LOG_OBJECT (trans, "handling buffer %p of size %d and offset %"        G_GUINT64_FORMAT, inbuf, GST_BUFFER_SIZE (inbuf),        GST_BUFFER_OFFSET (inbuf));  else    GST_LOG_OBJECT (trans, "handling buffer %p of size %d and offset NONE",        inbuf, GST_BUFFER_SIZE (inbuf));  /* Don't allow buffer handling before negotiation, except in passthrough mode   * or if the class doesn't implement a set_caps function (in which case it doesn't   * care about caps)   */  if (!trans->negotiated && !trans->passthrough && (bclass->set_caps != NULL))    goto not_negotiated;  /* Set discont flag so we can mark the outgoing buffer */  if (GST_BUFFER_IS_DISCONT (inbuf)) {    GST_LOG_OBJECT (trans, "got DISCONT buffer %p", inbuf);    trans->priv->discont = TRUE;  }  /* can only do QoS if the segment is in TIME */  if (trans->segment.format != GST_FORMAT_TIME)    goto no_qos;  qostime = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME,      GST_BUFFER_TIMESTAMP (inbuf));  if (qostime != -1) {    gboolean need_skip;    GstClockTime earliest_time;    GST_OBJECT_LOCK (trans);    earliest_time = trans->priv->earliest_time;    /* check for QoS, don't perform conversion for buffers     * that are known to be late. */    need_skip = trans->priv->qos_enabled &&        earliest_time != -1 && qostime != -1 && qostime <= earliest_time;    GST_OBJECT_UNLOCK (trans);    if (need_skip) {      GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, "skipping transform: qostime %"          GST_TIME_FORMAT " <= %" GST_TIME_FORMAT,          GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));      /* mark discont for next buffer */      trans->priv->discont = TRUE;      goto skip;    }  }no_qos:  if (trans->passthrough) {    /* In passthrough mode, give transform_ip a look at the     * buffer, without making it writable, or just push the     * data through */    GST_LOG_OBJECT (trans, "element is in passthrough mode");    if (bclass->transform_ip)      ret = bclass->transform_ip (trans, inbuf);    *outbuf = inbuf;    goto done;  }  want_in_place = (bclass->transform_ip != NULL) && trans->always_in_place;  *outbuf = NULL;  if (want_in_place) {    /* If want_in_place is TRUE, we may need to prepare a new output buffer     * Sub-classes can implement a prepare_output_buffer function as they     * wish. */    GST_LOG_OBJECT (trans, "doing inplace transform");    ret = gst_base_transform_prepare_output_buffer (trans, inbuf,        GST_BUFFER_SIZE (inbuf), GST_PAD_CAPS (trans->srcpad), outbuf);    if (G_UNLIKELY (ret != GST_FLOW_OK))      goto no_buffer;    ret = bclass->transform_ip (trans, *outbuf);  } else {    GST_LOG_OBJECT (trans, "doing non-inplace transform");    /* not transforming inplace, figure out the output size */    if (trans->always_in_place) {      out_size = GST_BUFFER_SIZE (inbuf);    } else {      if (!gst_base_transform_transform_size (trans,              GST_PAD_DIRECTION (trans->sinkpad), GST_PAD_CAPS (trans->sinkpad),              GST_BUFFER_SIZE (inbuf), GST_PAD_CAPS (trans->srcpad),              &out_size)) {        /* we have an error */        goto no_size;      }    }    /* no in place transform, get buffer, this might renegotiate. */    ret = gst_base_transform_prepare_output_buffer (trans, inbuf, out_size,        GST_PAD_CAPS (trans->srcpad), outbuf);    if (ret != GST_FLOW_OK)      goto no_buffer;

⌨️ 快捷键说明

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