[Converter] Get tensor metadata from sinkpad when it is created.
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Tue, 27 Mar 2018 10:46:36 +0000 (19:46 +0900)
committer함명주/동작제어Lab(SR)/Principal Engineer/삼성전자 <myungjoo.ham@samsung.com>
Wed, 28 Mar 2018 06:41:50 +0000 (15:41 +0900)
Sinkpad is created when a source element is attached to this filter (convert2filter).
Convert2filter becomes aware of its metadata (dimensions of tensor) at this point.
Thus, configure the metadata with the event handler.

Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
convert2tensor/convert2tensor.c
convert2tensor/convert2tensor.h

index 46dcd41..6d29bd4 100644 (file)
@@ -108,8 +108,11 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("other/tensor, "
-                       "rank = (int) [ 1, 4 ], "
-                      "dimension = (int) [ 0, 65536 ], (int) [ 0, 65536 ], (int) [ 0, 65536 ], (int) [0, 65536 ], "
+                       "rank = (uint) [ 1, 4 ], "
+                      "dim1 = (uint) [ 1, 65535 ], "
+                      "dim2 = (uint) [ 1, 65535 ], "
+                      "dim3 = (uint) [ 1, 65535 ], "
+                      "dim4 = (uint) [ 1, 65535 ], "
                       "type = (string) { float32, float64, int32, uint32, int16, uint16, int8, uint8 }, "
                       "framerate = (fraction) [ 0, 1024 ], ")
     );
@@ -177,6 +180,7 @@ gst_convert2tensor_init (GstConvert2Tensor * filter)
   gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
 
   filter->silent = FALSE;
+  filter->tensorConfigured = FALSE;
 }
 
 static void
@@ -211,11 +215,62 @@ gst_convert2tensor_get_property (GObject * object, guint prop_id,
   }
 }
 
-/* GstElement vmethod implementations */
+/******************************************************************
+ * GstElement vmethod implementations
+ */
 
+#define return_false_if_fail(x)        \
+  ret = (x); \
+  if (!ret) \
+    return FALSE; \
+  ;
 /* Configure tensor metadata from sink caps */
 static gboolean
-gst_convert2tensor_configure_tensor(const GstCaps *caps, GstConvert2Tensor *myself) {
+gst_convert2tensor_configure_tensor(const GstCaps *caps, GstConvert2Tensor *filter) {
+  GstStructure *structure;
+  gint rank;
+  gint dimension[GST_CONVERT2TENSOR_TENSOR_RANK_LIMIT];
+  tensor_type type;
+  gint framerate_numerator;
+  gint framerate_denominator;
+  gboolean ret;
+  GstCaps *outcaps;
+  int i;
+
+  /* This caps is coming from video/x-raw */
+  structure = gst_caps_get_structure(caps, 0);
+  rank = 3; /* [color-space][height][width] */
+  return_false_if_fail(gst_structure_get_int(structure, "width", &dimension[0]));
+  return_false_if_fail(gst_structure_get_int(structure, "height", &dimension[1]));
+  return_false_if_fail(gst_structure_get_fraction(structure, "framerate", &framerate_numerator, &framerate_denominator));
+  type = _C2T_UINT8; /* Assume color depth per component is 8 bit */
+  dimension[2] = 3; /* R G B */
+  dimension[3] = 1; /* This is 3-D Tensor */
+  /* Refer: https://gstreamer.freedesktop.org/documentation/design/mediatype-video-raw.html */
+
+  if (filter->tensorConfigured == TRUE) {
+    /* It has been already configured. Check if they are consistent */
+    if (rank == filter->rank &&
+       type == filter->type &&
+       framerate_numerator == filter->framerate_numerator &&
+       framerate_denominator == filter->framerate_denominator) {
+      for (i = 0; i < GST_CONVERT2TENSOR_TENSOR_RANK_LIMIT; i++)
+        if (dimension[i] != filter->dimension[i])
+         return FALSE;
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  filter->rank = rank;
+  for (i = 0; i < GST_CONVERT2TENSOR_TENSOR_RANK_LIMIT; i++)
+    filter->dimension[i] = dimension[i];
+  filter->type = type;
+  filter->framerate_numerator = framerate_numerator;
+  filter->framerate_denominator = framerate_denominator;
+
+  filter->tensorConfigured = TRUE;
+  return TRUE;
 }
 
 
@@ -237,9 +292,11 @@ gst_convert2tensor_sink_event (GstPad * pad, GstObject * parent, GstEvent * even
       GstCaps * caps;
 
       gst_event_parse_caps (event, &caps);
-      /* @TODO Construct tensor metadata from sink caps */
       ret = gst_convert2tensor_configure_tensor(caps, filter);
-
+      if (ret == FALSE) {
+        g_printerr("Cannot parse sinkpad caps properly for tensor metadata\n");
+        break; /* REPORT THIS INCIDENT! */
+      }
 
       /* and forward */
       ret = gst_pad_event_default (pad, parent, event);
index 0e6b682..9c91244 100644 (file)
@@ -73,6 +73,19 @@ typedef struct _GstConvert2Tensor GstConvert2Tensor;
 
 typedef struct _GstConvert2TensorClass GstConvert2TensorClass;
 
+#define GST_CONVERT2TENSOR_TENSOR_RANK_LIMIT   (4)
+typedef enum _tensor_type {
+      _C2T_INT32 = 0,
+      _C2T_UINT32,
+      _C2T_INT16,
+      _C2T_UINT16,
+      _C2T_INT8,
+      _C2T_UINT8,
+      _C2T_FLOAT64,
+      _C2T_FLOAT32,
+
+      _C2T_END,
+} tensor_type;
 struct _GstConvert2Tensor
 {
   GstElement element;  /**< This element itself is the convert2tensor filter */
@@ -80,20 +93,13 @@ struct _GstConvert2Tensor
   GstPad *srcpad;      /**< Tensor stream output */
   gboolean silent;     /**< True if logging is minimized */
   gboolean tensorConfigured;   /**< True if sinkpad has successfully configured tensor metadata */
-  int rank;            /**< Tensor Rank (# dimensions) */
-  int dimension[4];    /**< Dimensions. We support up to 4th ranks */
-  enum {
-        _C2T_INT32 = 0,
-        _C2T_UINT32,
-        _C2T_INT16,
-        _C2T_UINT16,
-        _C2T_INT8,
-        _C2T_UINT8,
-        _C2T_FLOAT64,
-        _C2T_FLOAT32,
-  } type;              /**< Type of each element in the tensor. User must designate this. Otherwise, this is UINT8 for video/x-raw byte stream */
+  gint rank;           /**< Tensor Rank (# dimensions) */
+  gint dimension[GST_CONVERT2TENSOR_TENSOR_RANK_LIMIT];        /**< Dimensions. We support up to 4th ranks */
+  tensor_type type;            /**< Type of each element in the tensor. User must designate this. Otherwise, this is UINT8 for video/x-raw byte stream */
+  gint framerate_numerator;    /**< framerate is in fraction, which is numerator/denominator */
+  gint framerate_denominator;  /**< framerate is in fraction, which is numerator/denominator */
 };
-unsigned int GstConvert2TensorDataSize[] = {
+const unsigned int GstConvert2TensorDataSize[] = {
         [_C2T_INT32] = 4,
         [_C2T_UINT32] = 4,
         [_C2T_INT16] = 2,
@@ -103,6 +109,17 @@ unsigned int GstConvert2TensorDataSize[] = {
         [_C2T_FLOAT64] = 8,
         [_C2T_FLOAT32] = 4,
 };
+const gchar* GstConvert2TensorDataTypeName[] = {
+        [_C2T_INT32] = "int32",
+        [_C2T_UINT32] = "uint32",
+        [_C2T_INT16] = "int16",
+        [_C2T_UINT16] = "uint16",
+        [_C2T_INT8] = "int8",
+        [_C2T_UINT8] = "uint8",
+        [_C2T_FLOAT64] = "float64",
+        [_C2T_FLOAT32] = "float32",
+};
+
 
 struct _GstConvert2TensorClass 
 {