}
return ret;
}
+
+/**
+ * @brief A callback for typefind, trying to find whether a file is other/tensors or not.
+ * For the concrete definition of headers, please look at the wiki page of nnstreamer:
+ * https://github.com/nnsuite/nnstreamer/wiki/Design-External-Save-Format-for-other-tensor-and-other-tensors-Stream-for-TypeFind
+ */
+void
+gst_tensors_typefind_function (GstTypeFind * tf, gpointer pdata)
+{
+ const guint8 *data = gst_type_find_peek (tf, 0, 40); /* The first 40 bytes are header-0 in v.1 protocol */
+ const char formatstr[] = "TENSORST";
+ const unsigned int *supported_version = (const unsigned int *) (&data[8]);
+ const unsigned int *num_tensors = (const unsigned int *) (&data[12]);
+ if (data &&
+ memcmp (data, formatstr, 8) == 0 &&
+ *supported_version == 1 && *num_tensors <= 16 && *num_tensors >= 1) {
+ gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
+ gst_caps_new_simple ("other/tensorsave", NULL, NULL));
+ }
+}
- framerate; fraction
- data: (binary data, can be treated as an C array of [dim4][dim3][dim2][dim1])
+
+# other/tensors File Data Format, Version 1.0 Draft
+
+```
+Header-0: The first 20 bytes, global header
+=============================================================================================================
+| 8 bytes | 4 bytes | 4 bytes | 4 bytes |
+| The type header | Protocol Version | Number of tensors per frame | Frame size in bytes |
+| "TENSORST" | (uint32) 1 | (uint32) 1~16 (N) | (uint32) 1 ~ MAXUINT (S) |
+| | | (v.1 supports up to 16) | Counting data only (no meta) |
+=============================================================================================================
+| 20 bytes. RESERVED in v1. |
+=============================================================================================================
+| Header-1: Following Header-1, Description of Tensor-1 of each frame (24 bytes) |
+| 4 bytes | 4 bytes | 4 bytes | 4 bytes | 4 bytes | 4 bytes |
+| Element Type (enum) | RANK (uint32) | Dim-1 | Dime-2 | Dim-3 | Dim-4 |
+| "tensor_type" in tensor_typedef.h | v.1 supports 1 to 4. | | | | |
+====================================================================================================
+| ... |
+====================================================================================================
+| Header-N |
+====================================================================================================
+Data of frame-1, tensor-1 starts at the offset of (40 + 24 x N).
+Data of frame-1, tensor-i starts at the offset of (40 + 24 x N + Sum(x=1..i-1)(tensor_element_size[tensor-type of Tx] x dim1-of-Tx x dim2-of-Tx x dim3-of-Tx x dim4-of-Tx)).
+...
+Data of frame-F, tensor-1 starts at the offset of (40 + 24 x N + S x (F - 1))
+...
+Assert (S = Sum(x=1..N)(tensor_element_size[tensor-type of Tx] x dim1-of-Tx x dim2-of-Tx x dim3-of-Tx x dim4-of-Tx))
+
+Add a custom footer
+```
+
+Note that once the stream is loaded in GStreamer, tensor\_\* elements uses the data parts only without the headers.
+The header exists only when the tensor stream is stored as a file.
--- /dev/null
+- tensor\_load: other/tensorsave to other/tensors or other/tensor
+- tensor\_save: other/tensors or other/tensor to other/tensorsave
*/
#define err_print(...) dlog_print(DLOG_ERROR, "nnstreamer", __VA_ARGS__)
+/**
+ * @brief A callback for typefind, trying to find whether a file is other/tensors or not.
+ * For the concrete definition of headers, please look at the wiki page of nnstreamer:
+ * https://github.com/nnsuite/nnstreamer/wiki/Design-External-Save-Format-for-other-tensor-and-other-tensors-Stream-for-TypeFind
+ */
+extern void gst_tensors_typefind_function (GstTypeFind *tf, gpointer pdata);
+
+#define GST_TENSOR_TYPEFIND_REGISTER(plugin) do { \
+ gst_type_find_register (plugin, "other/tensorsave", \
+ GST_RANK_PRIMARY, gst_tensors_typefind_function, "tnsr", \
+ gst_caps_new_simple ("other/tensorsave", NULL, NULL), NULL, NULL)); \
+ } while (0)
+
G_END_DECLS
#endif /* __GST_TENSOR_COMMON_H__ */