gst_caps_new_simple ("other/tensorsave", NULL, NULL));
}
}
+
+/**
+ * @brief A function call to decide current timestamp among collected pads based on PTS.
+ * It will decide current timestamp according to synch option.
+ */
+gboolean
+gst_tensor_set_current_time (GstCollectPads * collect,
+ GstClockTime * current_time, tensor_time_synch_mode synch)
+{
+ GSList *walk = NULL;
+ walk = collect->data;
+ gboolean isEOS = FALSE;
+
+ while (walk) {
+ GstCollectData *data = (GstCollectData *) walk->data;
+ walk = g_slist_next (walk);
+ GstBuffer *buf = NULL;
+ buf = gst_collect_pads_peek (collect, data);
+
+ if (buf == NULL) {
+ isEOS = TRUE;
+ return isEOS;
+ }
+
+ switch (synch) {
+ case SYNCH_SLOWEST:
+ if (*current_time < GST_BUFFER_PTS (buf))
+ *current_time = GST_BUFFER_PTS (buf);
+ gst_buffer_unref (buf);
+ break;
+ case SYNCH_BASEPAD:
+ break;
+ default:
+ break;
+ }
+ }
+
+ return isEOS;
+}
+
+/**
+ * @brief A function call to make tensors from collected pads.
+ * It decide which buffer is going to be used according to synch option.
+ */
+gboolean
+gst_gen_tensors_from_collectpad (GstCollectPads * collect,
+ tensor_time_synch_mode synch, GstClockTime current_time,
+ gboolean * need_buffer, GstBuffer * tensors_buf, GstTensorsConfig * configs)
+{
+ GSList *walk = NULL;
+ GstMemory *mem;
+ gboolean isEOS = FALSE;
+ gint old_numerator = G_MAXINT;
+ gint old_denominator = G_MAXINT;
+ gint counting = 0;
+ GstTensorConfig config;
+
+ walk = collect->data;
+ while (walk) {
+ GstCollectData *data = (GstCollectData *) walk->data;
+ GstTensorCollectPadData *pad = (GstTensorCollectPadData *) data;
+ GstCaps *caps = gst_pad_get_current_caps (pad->pad);
+ GstStructure *s = gst_caps_get_structure (caps, 0);
+
+ gst_tensor_config_from_structure (&config, s);
+ g_assert (gst_tensor_config_validate (&config));
+
+ if (config.rate_d < old_denominator)
+ old_denominator = config.rate_d;
+ if (config.rate_n < old_numerator)
+ old_numerator = config.rate_n;
+
+ gst_caps_unref (caps);
+
+ walk = g_slist_next (walk);
+
+ GstBuffer *buf = NULL;
+
+ buf = gst_collect_pads_peek (collect, data);
+
+ if (buf == NULL && pad->buffer == NULL) {
+ isEOS = TRUE;
+ return isEOS;
+ }
+
+ switch (synch) {
+ case SYNCH_SLOWEST:
+ {
+ if (buf != NULL) {
+ if (GST_BUFFER_PTS (buf) < current_time) {
+ gst_buffer_unref (buf);
+ if (pad->buffer != NULL)
+ gst_buffer_unref (pad->buffer);
+ pad->buffer = gst_collect_pads_pop (collect, data);
+ *need_buffer = TRUE;
+ return FALSE;
+ }
+
+ if (pad->buffer != NULL &&
+ (ABS (GST_CLOCK_DIFF (current_time,
+ GST_BUFFER_PTS (pad->buffer))) <
+ ABS (GST_CLOCK_DIFF (current_time, GST_BUFFER_PTS (buf))))) {
+ gst_buffer_unref (buf);
+ buf = pad->buffer;
+ } else {
+ gst_buffer_unref (buf);
+ buf = gst_collect_pads_pop (collect, data);
+ if (pad->buffer != NULL)
+ gst_buffer_unref (pad->buffer);
+ pad->buffer = buf;
+ }
+ } else {
+ buf = pad->buffer;
+ }
+
+ }
+ break;
+ default:
+ gst_buffer_unref (buf);
+ buf = gst_collect_pads_pop (collect, data);
+ }
+
+ if (GST_IS_BUFFER (buf)) {
+ mem = gst_buffer_get_memory (buf, 0);
+ gst_buffer_append_memory (tensors_buf, mem);
+
+ if (synch == SYNCH_NOSYNCH)
+ gst_buffer_unref (buf);
+ else
+ pad->buffer = buf;
+ } else {
+ isEOS = TRUE;
+ }
+
+ configs->info.info[counting] = config.info;
+ counting++;
+ }
+
+ configs->rate_d = old_denominator;
+ configs->rate_n = old_numerator;
+
+ GST_BUFFER_PTS (tensors_buf) = current_time;
+ return isEOS;
+}
#include <gst/gst.h>
#include <gst/video/video-format.h>
#include <gst/audio/audio-format.h>
+#include <gst/base/gstcollectpads.h>
#include <gst/gstplugin.h>
G_BEGIN_DECLS
} GstTensorsConfig;
/**
+ * @brief time synchronization options
+ */
+
+typedef enum
+{
+ SYNCH_NOSYNCH = 0,
+ SYNCH_SLOWEST = 1,
+ SYNCH_BASEPAD = 2,
+ SYNCH_END,
+} tensor_time_synch_mode;
+
+/**
+ * @brief Internal data structure for Collect Pad in mux / merge
+ */
+typedef struct
+{
+ GstCollectData collect;
+ GstClockTime pts_timestamp;
+ GstClockTime dts_timestamp;
+ GstBuffer *buffer;
+ GstPad *pad;
+} GstTensorCollectPadData;
+
+/**
* @brief String representations for each tensor element type.
*/
extern const gchar *tensor_element_typename[];
static gboolean G_PASTE(G_PASTE(gst_, name), _plugin_init) (GstPlugin * plugin)
#endif
+
+/**
+ * @brief A function call to decide current timestamp among collected pads based on PTS.
+ * It will decide current timestamp according to synch option.
+ * @return True / False if EOS, it return TRUE.
+ * @param collect Collect pad.
+ * @param current_time Current time
+ * @param synch Synchronization Option (NOSYNCH, SLOWEST, BASEPAD, END)
+ */
+extern gboolean gst_tensor_set_current_time(GstCollectPads *collect, GstClockTime *current_time, tensor_time_synch_mode synch);
+
+/**
+ * @brief A function call to make tensors from collected pads
+ * It decide which buffer is going to be used according to synch option.
+ * @return True / False if EOS, it return TRUE.
+ * @param collect Collect pad.
+ * @param synch Synchronization Option (NOSYNCH, SLOWEST, BASEPAD, END)
+ * @param current_time Current Timestamp
+ * @param need_buffer Boolean for Update Collect Pads
+ * @param tensors_buf Generated GstBuffer for Collected Buffer
+ * @param configs Configuration Info for Collected Buffer
+ */
+extern gboolean gst_gen_tensors_from_collectpad (GstCollectPads * collect, tensor_time_synch_mode synch, GstClockTime current_time, gboolean *need_buffer, GstBuffer *tensors_buf, GstTensorsConfig *configs);
+
G_END_DECLS
#endif /* __GST_TENSOR_COMMON_H__ */
if (newpad) {
- GstTensorMergePadData *tensormergepad;
+ GstTensorCollectPadData *tensormergepad;
- tensormergepad = (GstTensorMergePadData *)
+ tensormergepad = (GstTensorCollectPadData *)
gst_collect_pads_add_pad (tensor_merge->collect, newpad,
- sizeof (GstTensorMergePadData), NULL, TRUE);
+ sizeof (GstTensorCollectPadData), NULL, TRUE);
tensormergepad->pad = newpad;
gst_pad_set_element_private (newpad, tensormergepad);
}
/**
- * @brief Compare dts & pts time and find earliest
- * @param tensor_merge tensor merger
- * @param old_data previous merge pad data
- * @param new_data current merge pad data
- * @return if > 0, new is earlier than old
- */
-static gint
-gst_tensor_merge_compare_pads (GstTensorMerge * tensor_merge,
- GstTensorMergePadData * old_data, GstTensorMergePadData * new_data)
-{
- guint64 oldtime, newtime;
- if (old_data == NULL)
- return 1;
- if (new_data == NULL)
- return -1;
- if (GST_CLOCK_TIME_IS_VALID (old_data->dts_timestamp) &&
- GST_CLOCK_TIME_IS_VALID (new_data->dts_timestamp)) {
- oldtime = old_data->dts_timestamp;
- newtime = new_data->dts_timestamp;
- } else {
- oldtime = old_data->pts_timestamp;
- newtime = new_data->pts_timestamp;
- }
-
- if (!GST_CLOCK_TIME_IS_VALID (oldtime))
- return -1;
- if (!GST_CLOCK_TIME_IS_VALID (newtime))
- return 1;
-
- if (newtime < oldtime)
- return 1;
- else if (newtime > oldtime)
- return -1;
-
- return 0;
-}
-
-/**
* @brief Generate TensorConfig with TensorsConfig
* @param tensor_merge tensor merger
* @param configs Tensors Config Data
gst_tensor_merge_collect_buffer (GstTensorMerge * tensor_merge,
GstBuffer * tensors_buf, GstClockTime * pts_time, GstClockTime * dts_time)
{
- GSList *walk = NULL;
- GstTensorMergePadData *bestpad = NULL;
- GstMemory *mem;
gboolean isEOS = FALSE;
- gint old_numerator = G_MAXINT;
- gint old_denominator = G_MAXINT;
- gint counting = 0;
- GstTensorConfig config;
-
- walk = tensor_merge->collect->data;
-
+ int synch_option = 0;
+ if (tensor_merge->synch)
+ synch_option = SYNCH_SLOWEST;
+ /* TODO Should set synch option properly. Currently SLOWEST is default */
if (tensor_merge->synch && tensor_merge->need_set_time) {
- while (walk) {
- GstCollectData *data = (GstCollectData *) walk->data;
- walk = g_slist_next (walk);
-
- GstBuffer *buf = NULL;
-
- buf = gst_collect_pads_peek (tensor_merge->collect, data);
+ if (gst_tensor_set_current_time (tensor_merge->collect,
+ &tensor_merge->current_time, synch_option))
+ return TRUE;
- if (buf == NULL)
- return TRUE;
-
- if (tensor_merge->current_time < GST_BUFFER_PTS (buf))
- tensor_merge->current_time = GST_BUFFER_PTS (buf);
- gst_buffer_unref (buf);
- }
tensor_merge->need_set_time = FALSE;
}
+ /* TODO Should set synch option properly. Currently SLOWEST is default */
+ isEOS =
+ gst_gen_tensors_from_collectpad (tensor_merge->collect, synch_option,
+ tensor_merge->current_time, &tensor_merge->need_buffer, tensors_buf,
+ &tensor_merge->tensors_config);
- walk = tensor_merge->collect->data;
-
- while (walk) {
- GstCollectData *data = (GstCollectData *) walk->data;
- GstTensorMergePadData *pad = (GstTensorMergePadData *) data;
- GstCaps *caps = gst_pad_get_current_caps (pad->pad);
- GstStructure *s = gst_caps_get_structure (caps, 0);
-
- gst_tensor_config_from_structure (&config, s);
- g_assert (gst_tensor_config_validate (&config));
-
- if (config.rate_d < old_denominator)
- old_denominator = config.rate_d;
- if (config.rate_n < old_numerator)
- old_numerator = config.rate_n;
-
- gst_caps_unref (caps);
-
- walk = g_slist_next (walk);
-
- GstBuffer *buf = NULL;
-
- if (tensor_merge->synch) {
- buf = gst_collect_pads_peek (tensor_merge->collect, data);
-
- if (buf == NULL && pad->buffer == NULL)
- return TRUE;
-
- if (buf != NULL) {
- if (GST_BUFFER_PTS (buf) < tensor_merge->current_time) {
- gst_buffer_unref (buf);
- if (pad->buffer != NULL)
- gst_buffer_unref (pad->buffer);
- pad->buffer = gst_collect_pads_pop (tensor_merge->collect, data);
- silent_debug ("Fame Dropped : %lu", GST_BUFFER_PTS (pad->buffer));
- tensor_merge->need_buffer = TRUE;
- return FALSE;
- }
-
- if (pad->buffer != NULL &&
- (ABS (GST_CLOCK_DIFF (tensor_merge->current_time,
- GST_BUFFER_PTS (pad->buffer))) <
- ABS (GST_CLOCK_DIFF (tensor_merge->current_time,
- GST_BUFFER_PTS (buf))))) {
- gst_buffer_unref (buf);
- buf = pad->buffer;
- } else {
- gst_buffer_unref (buf);
- buf = gst_collect_pads_pop (tensor_merge->collect, data);
- if (pad->buffer != NULL)
- gst_buffer_unref (pad->buffer);
- pad->buffer = buf;
- }
- } else {
- buf = pad->buffer;
- }
- } else {
- buf = gst_collect_pads_pop (tensor_merge->collect, data);
- }
-
- if (GST_IS_BUFFER (buf)) {
- mem = gst_buffer_get_memory (buf, 0);
- gst_buffer_append_memory (tensors_buf, mem);
- pad->buffer = buf;
- silent_debug ("Append Memory # %d (PTS : %lu)",
- gst_buffer_n_memory (tensors_buf), GST_BUFFER_PTS (buf));
-
- if (gst_tensor_merge_compare_pads (tensor_merge, bestpad, pad) > 0) {
- bestpad = pad;
- *pts_time = bestpad->pts_timestamp;
- *dts_time = bestpad->dts_timestamp;
- }
-
- if (!tensor_merge->synch)
- gst_buffer_unref (buf);
- } else {
- isEOS = TRUE;
- }
-
- tensor_merge->tensors_config.info.info[counting] = config.info;
- counting++;
- }
+ if (tensor_merge->need_buffer)
+ return FALSE;
- tensor_merge->tensors_config.rate_d = old_denominator;
- tensor_merge->tensors_config.rate_n = old_numerator;
+ *pts_time = GST_BUFFER_PTS (tensors_buf);
+ *dts_time = GST_BUFFER_DTS (tensors_buf);
- /* set timestamp */
- GST_BUFFER_PTS (tensors_buf) = *pts_time;
- GST_BUFFER_DTS (tensors_buf) = *dts_time;
return isEOS;
}
#define __GST_TENSOR_MERGE_H__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
#include <tensor_common.h>
G_BEGIN_DECLS
tensor_merge_linear_mode direction;
} tensor_merge_linear;
-
-typedef struct
-{
- GstCollectData collect;
- GstClockTime pts_timestamp;
- GstClockTime dts_timestamp;
- GstBuffer *buffer;
- GstPad *pad;
-} GstTensorMergePadData;
-
/**
* @brief Tensor Merge data structure
*/
g_free (name);
if (newpad) {
- GstTensorMuxPadData *tensormuxpad;
- tensormuxpad =
- (GstTensorMuxPadData *) gst_collect_pads_add_pad (tensor_mux->collect,
- newpad, sizeof (GstTensorMuxPadData), NULL, TRUE);
+ GstTensorCollectPadData *tensormuxpad;
+ tensormuxpad = (GstTensorCollectPadData *)
+ gst_collect_pads_add_pad (tensor_mux->collect, newpad,
+ sizeof (GstTensorCollectPadData), NULL, TRUE);
tensormuxpad->pad = newpad;
gst_pad_set_element_private (newpad, tensormuxpad);
tensor_mux->tensors_config.info.num_tensors++;
}
/**
- * @brief Compare dts & pts time and find earliest
- * @param tensor_mux tensor muxer
- * @param old_data previous mux pad data
- * @param new_data current mux pad data
- * @return if > 0, new is earlier than old
- */
-static gint
-gst_tensor_mux_compare_pads (GstTensorMux * tensor_mux,
- GstTensorMuxPadData * old_data, GstTensorMuxPadData * new_data)
-{
- guint64 oldtime, newtime;
- if (old_data == NULL)
- return 1;
- if (new_data == NULL)
- return -1;
- if (GST_CLOCK_TIME_IS_VALID (old_data->dts_timestamp) &&
- GST_CLOCK_TIME_IS_VALID (new_data->dts_timestamp)) {
- oldtime = old_data->dts_timestamp;
- newtime = new_data->dts_timestamp;
- } else {
- oldtime = old_data->pts_timestamp;
- newtime = new_data->pts_timestamp;
- }
-
- if (!GST_CLOCK_TIME_IS_VALID (oldtime))
- return -1;
- if (!GST_CLOCK_TIME_IS_VALID (newtime))
- return 1;
-
- if (newtime < oldtime)
- return 1;
- else if (newtime > oldtime)
- return -1;
-
- return 0;
-}
-
-/**
* @brief Looping to generete outbut buffer for srcpad
* @param tensor_mux tensor muxer
* @param tensors_buf output buffer for srcpad
gst_tensor_mux_collect_buffer (GstTensorMux * tensor_mux,
GstBuffer * tensors_buf, GstClockTime * pts_time, GstClockTime * dts_time)
{
- GSList *walk = NULL;
- GstTensorMuxPadData *bestpad = NULL;
- GstMemory *mem;
gboolean isEOS = FALSE;
- gint old_numerator = G_MAXINT;
- gint old_denominator = G_MAXINT;
- gint counting = 0;
- GstTensorConfig config;
-
- walk = tensor_mux->collect->data;
-
+ int synch_option = 0;
+ if (tensor_mux->synch)
+ synch_option = SYNCH_SLOWEST;
if (tensor_mux->synch && tensor_mux->need_set_time) {
- while (walk) {
- GstCollectData *data = (GstCollectData *) walk->data;
- walk = g_slist_next (walk);
-
- GstBuffer *buf = NULL;
- buf = gst_collect_pads_peek (tensor_mux->collect, data);
-
- if (buf == NULL)
- return TRUE;
-
- if (tensor_mux->current_time < GST_BUFFER_PTS (buf))
- tensor_mux->current_time = GST_BUFFER_PTS (buf);
- gst_buffer_unref (buf);
- }
+ /* TODO Should set synch option properly. Currently SLOWEST is default */
+ if (gst_tensor_set_current_time (tensor_mux->collect,
+ &tensor_mux->current_time, synch_option))
+ return TRUE;
tensor_mux->need_set_time = FALSE;
silent_debug ("Current Time : %lu", tensor_mux->current_time);
}
- walk = tensor_mux->collect->data;
-
- while (walk) {
- GstCollectData *data = (GstCollectData *) walk->data;
- GstTensorMuxPadData *pad = (GstTensorMuxPadData *) data;
- GstCaps *caps = gst_pad_get_current_caps (pad->pad);
- GstStructure *s = gst_caps_get_structure (caps, 0);
-
- gst_tensor_config_from_structure (&config, s);
- g_assert (gst_tensor_config_validate (&config));
-
- if (config.rate_d < old_denominator)
- old_denominator = config.rate_d;
- if (config.rate_n < old_numerator)
- old_numerator = config.rate_n;
-
- gst_caps_unref (caps);
-
- walk = g_slist_next (walk);
-
- GstBuffer *buf = NULL;
-
- if (tensor_mux->synch) {
- buf = gst_collect_pads_peek (tensor_mux->collect, data);
- if (buf == NULL && pad->buffer == NULL)
- return TRUE;
-
- if (buf != NULL) {
- if (GST_BUFFER_PTS (buf) < tensor_mux->current_time) {
- gst_buffer_unref (buf);
- if (pad->buffer != NULL)
- gst_buffer_unref (pad->buffer);
- pad->buffer = gst_collect_pads_pop (tensor_mux->collect, data);
- silent_debug ("Fame Dropped (# %d) : %lu", counting,
- GST_BUFFER_PTS (pad->buffer));
- tensor_mux->need_buffer = TRUE;
- return FALSE;
- }
-
- if (pad->buffer != NULL &&
- (ABS (GST_CLOCK_DIFF (tensor_mux->current_time,
- GST_BUFFER_PTS (pad->buffer))) <
- ABS (GST_CLOCK_DIFF (tensor_mux->current_time,
- GST_BUFFER_PTS (buf))))) {
- gst_buffer_unref (buf);
- buf = pad->buffer;
- } else {
- gst_buffer_unref (buf);
- buf = gst_collect_pads_pop (tensor_mux->collect, data);
- if (pad->buffer != NULL)
- gst_buffer_unref (pad->buffer);
- pad->buffer = buf;
- }
- } else {
- buf = pad->buffer;
- }
- } else {
- buf = gst_collect_pads_pop (tensor_mux->collect, data);
- }
-
- if (GST_IS_BUFFER (buf)) {
- mem = gst_buffer_get_memory (buf, 0);
- gst_buffer_append_memory (tensors_buf, mem);
- pad->buffer = buf;
-
- silent_debug ("Append Memory # %d (PTS : %lu)",
- gst_buffer_n_memory (tensors_buf), GST_BUFFER_PTS (buf));
-
- if (gst_tensor_mux_compare_pads (tensor_mux, bestpad, pad) > 0) {
- bestpad = pad;
- *pts_time = bestpad->pts_timestamp;
- *dts_time = bestpad->dts_timestamp;
- }
-
- if (!tensor_mux->synch)
- gst_buffer_unref (buf);
- } else {
- isEOS = TRUE;
- }
-
- tensor_mux->tensors_config.info.info[counting] = config.info;
- counting++;
- }
+ /* TODO Should set synch option properly. Currently SLOWEST is default */
+ isEOS =
+ gst_gen_tensors_from_collectpad (tensor_mux->collect, synch_option,
+ tensor_mux->current_time, &tensor_mux->need_buffer, tensors_buf,
+ &tensor_mux->tensors_config);
- tensor_mux->tensors_config.rate_d = old_denominator;
- tensor_mux->tensors_config.rate_n = old_numerator;
+ if (tensor_mux->need_buffer)
+ return FALSE;
- debug_print (!tensor_mux->silent, "pts %" GST_TIME_FORMAT,
- GST_TIME_ARGS (*pts_time));
- debug_print (!tensor_mux->silent, "dts %" GST_TIME_FORMAT,
- GST_TIME_ARGS (*dts_time));
+ *pts_time = GST_BUFFER_PTS (tensors_buf);
+ *dts_time = GST_BUFFER_DTS (tensors_buf);
- /* set timestamp */
- GST_BUFFER_PTS (tensors_buf) = *pts_time;
- GST_BUFFER_DTS (tensors_buf) = *dts_time;
return isEOS;
}
#define __GST_TENSOR_MUX_H__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
#include <tensor_common.h>
G_BEGIN_DECLS
typedef struct _GstTensorMux GstTensorMux;
typedef struct _GstTensorMuxClass GstTensorMuxClass;
-
-
-typedef struct
-{
- GstCollectData collect;
- GstClockTime pts_timestamp;
- GstClockTime dts_timestamp;
- GstBuffer *buffer;
- GstPad *pad;
-} GstTensorMuxPadData;
-
/**
* @brief Tensor Muxer data structure
*/