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; }
/** * @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; } }