static GstFlowReturn
gst_chop_my_data_process (GstChopMyData * chopmydata, gboolean flush)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *buffer;

  if (chopmydata->next_size == 0) {
    get_next_size (chopmydata);
  }

  while (gst_adapter_available (chopmydata->adapter) >= chopmydata->next_size) {
    buffer =
        gst_adapter_take_buffer (chopmydata->adapter, chopmydata->next_size);

    GST_BUFFER_PTS (buffer) = gst_adapter_prev_pts (chopmydata->adapter, NULL);
    GST_BUFFER_DTS (buffer) = gst_adapter_prev_dts (chopmydata->adapter, NULL);

    chopmydata->next_size = 0;

    ret = gst_pad_push (chopmydata->srcpad, buffer);
    if (ret != GST_FLOW_OK) {
      return ret;
    }

    get_next_size (chopmydata);
  }

  if (flush) {
    guint min_size = chopmydata->min_size;

    while (gst_adapter_available (chopmydata->adapter) >= min_size) {
      buffer = gst_adapter_take_buffer (chopmydata->adapter, min_size);
      ret = gst_pad_push (chopmydata->srcpad, buffer);
      if (ret != GST_FLOW_OK)
        break;
    }
    gst_adapter_clear (chopmydata->adapter);
  }

  return ret;
}
Example #2
0
/**
 * @brief Chain function, this function does the actual processing.
 */
static GstFlowReturn
gst_tensor_aggregator_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstTensorAggregator *self;
  GstFlowReturn ret = GST_FLOW_OK;
  GstAdapter *adapter;
  gsize avail, buf_size, frame_size, out_size;
  guint frames_in, frames_out, frames_flush;
  GstClockTime duration;

  self = GST_TENSOR_AGGREGATOR (parent);
  g_assert (self->tensor_configured);

  buf_size = gst_buffer_get_size (buf);
  g_return_val_if_fail (buf_size > 0, GST_FLOW_ERROR);

  frames_in = self->frames_in;
  frames_out = self->frames_out;
  frames_flush = self->frames_flush;
  frame_size = buf_size / frames_in;

  if (frames_in == frames_out) {
    /** push the incoming buffer (do concat if needed) */
    return gst_tensor_aggregator_push (self, buf, frame_size);
  }

  adapter = self->adapter;
  g_assert (adapter != NULL);

  duration = GST_BUFFER_DURATION (buf);
  if (GST_CLOCK_TIME_IS_VALID (duration)) {
    /** supposed same duration for incoming buffer */
    duration = gst_util_uint64_scale_int (duration, frames_out, frames_in);
  }

  gst_adapter_push (adapter, buf);

  out_size = frame_size * frames_out;
  g_assert (out_size > 0);

  while ((avail = gst_adapter_available (adapter)) >= out_size &&
      ret == GST_FLOW_OK) {
    GstBuffer *outbuf;
    GstClockTime pts, dts;
    guint64 pts_dist, dts_dist;
    gsize flush;

    pts = gst_adapter_prev_pts (adapter, &pts_dist);
    dts = gst_adapter_prev_dts (adapter, &dts_dist);

    /**
     * Update timestamp.
     * If frames-in is larger then frames-out, the same timestamp (pts and dts) would be returned.
     */
    if (frames_in > 1) {
      gint fn, fd;

      fn = self->in_config.rate_n;
      fd = self->in_config.rate_d;

      if (fn > 0 && fd > 0) {
        if (GST_CLOCK_TIME_IS_VALID (pts)) {
          pts +=
              gst_util_uint64_scale_int (pts_dist * fd, GST_SECOND,
              fn * frame_size);
        }

        if (GST_CLOCK_TIME_IS_VALID (dts)) {
          dts +=
              gst_util_uint64_scale_int (dts_dist * fd, GST_SECOND,
              fn * frame_size);
        }
      }
    }

    outbuf = gst_adapter_get_buffer (adapter, out_size);
    outbuf = gst_buffer_make_writable (outbuf);

    /** set timestamp */
    GST_BUFFER_PTS (outbuf) = pts;
    GST_BUFFER_DTS (outbuf) = dts;
    GST_BUFFER_DURATION (outbuf) = duration;

    ret = gst_tensor_aggregator_push (self, outbuf, frame_size);

    /** flush data */
    if (frames_flush > 0) {
      flush = frame_size * frames_flush;

      if (flush > avail) {
        /**
         * @todo flush data
         * Invalid state, tried to flush large size.
         * We have to determine how to handle this case. (flush the out-size or all available bytes)
         * Now all available bytes in adapter will be flushed.
         */
        flush = avail;
      }
    } else {
      flush = out_size;
    }

    gst_adapter_flush (adapter, flush);
  }

  return ret;
}
static void
stop_typefinding (GstTypeFindElement * typefind)
{
  GstState state;
  gboolean push_cached_buffers;
  gsize avail;
  GstBuffer *buffer;
  GstClockTime pts, dts;

  gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);

  push_cached_buffers = (state >= GST_STATE_PAUSED && typefind->caps);

  GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
      push_cached_buffers ? " and pushing cached events and buffers" : "");

  typefind->mode = MODE_NORMAL;
  if (push_cached_buffers)
    gst_type_find_element_send_cached_events (typefind);

  GST_OBJECT_LOCK (typefind);
  avail = gst_adapter_available (typefind->adapter);
  if (avail == 0)
    goto no_data;

  pts = gst_adapter_prev_pts (typefind->adapter, NULL);
  dts = gst_adapter_prev_dts (typefind->adapter, NULL);
  buffer = gst_adapter_take_buffer (typefind->adapter, avail);
  GST_BUFFER_PTS (buffer) = pts;
  GST_BUFFER_DTS (buffer) = dts;
  GST_BUFFER_OFFSET (buffer) = typefind->initial_offset;
  GST_OBJECT_UNLOCK (typefind);

  if (!push_cached_buffers) {
    gst_buffer_unref (buffer);
  } else {
    GstPad *peer = gst_pad_get_peer (typefind->src);

    /* make sure the user gets a meaningful error message in this case,
     * which is not a core bug or bug of any kind (as the default error
     * message emitted by gstpad.c otherwise would make you think) */
    if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
      GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
          "downstream element only works in pull mode, erroring out");
      GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
          ("%s cannot work in push mode. The operation is not supported "
              "with this source element or protocol.",
              G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
          ("Downstream pad %s:%s has no chainfunction, and the upstream "
              "element does not support pull mode", GST_DEBUG_PAD_NAME (peer)));
      typefind->mode = MODE_ERROR;      /* make the chain function error out */
      gst_buffer_unref (buffer);
    } else {
      gst_pad_push (typefind->src, buffer);
    }
    if (peer)
      gst_object_unref (peer);
  }
  return;

  /* ERRORS */
no_data:
  {
    GST_DEBUG_OBJECT (typefind, "we have no data to typefind");
    GST_OBJECT_UNLOCK (typefind);
    return;
  }
}