Add common util and use stack
authorInki Dae <inki.dae@samsung.com>
Thu, 24 Sep 2020 09:35:57 +0000 (18:35 +0900)
committerInki Dae <inki.dae@samsung.com>
Thu, 24 Sep 2020 09:35:57 +0000 (18:35 +0900)
Change-Id: I274b8774133c286442a5b74e6a1194e84de1055e
Signed-off-by: Inki Dae <inki.dae@samsung.com>
test/testsuites/stream_infer/CMakeLists.txt
test/testsuites/stream_infer/stream_infer_armnn.c
test/testsuites/stream_infer/stream_infer_common_util.c [new file with mode: 0644]
test/testsuites/stream_infer/stream_infer_common_util.h [new file with mode: 0644]

index d1464f6b0147e207c35dfb1c3b70fbc94fd18994..9be8aace2c357aaeb5fa61b0e98f2957b0540572 100644 (file)
@@ -11,6 +11,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${LIB_INSTALL_DIR})
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
 
 include_directories(${PROJECT_SOURCE_DIR})
+include_directories(${PROJECT_SOURCE_DIR}/stream_infer)
 include_directories(${MV_CAPI_MEDIA_VISION_INC_DIR})
 include_directories(${INC_IMAGE_HELPER})
 include_directories(${INC_VIDEO_HELPER})
@@ -46,6 +47,7 @@ SET(CMAKE_C_FLAGS "-I./include -I./include/headers ${CMAKE_C_FLAGS} ${EXTRA_CFLA
 SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
 
 add_executable(${TFLITE_TEST}
+                          ${PROJECT_SOURCE_DIR}/stream_infer/stream_infer_common_util.c
                           ${PROJECT_SOURCE_DIR}/stream_infer/stream_infer.c
                           ${MV_CAPI_MEDIA_VISION_INC_LIST})
 
@@ -65,6 +67,7 @@ target_link_libraries(${TFLITE_TEST} ${MV_INFERENCE_LIB_NAME}
 install(TARGETS ${TFLITE_TEST} DESTINATION ${testbin_dir})
 
 add_executable(${MLAPI_TEST}
+                          ${PROJECT_SOURCE_DIR}/stream_infer/stream_infer_common_util.c
                           ${PROJECT_SOURCE_DIR}/stream_infer/stream_infer_mlapi.c
                           ${MV_CAPI_MEDIA_VISION_INC_LIST})
 
@@ -84,6 +87,7 @@ target_link_libraries(${MLAPI_TEST} ${MV_INFERENCE_LIB_NAME}
 install(TARGETS ${MLAPI_TEST} DESTINATION ${testbin_dir})
 
 add_executable(${ARMNN_TEST}
+                          ${PROJECT_SOURCE_DIR}/stream_infer/stream_infer_common_util.c
                           ${PROJECT_SOURCE_DIR}/stream_infer/stream_infer_armnn.c
                           ${MV_CAPI_MEDIA_VISION_INC_LIST})
 
index c00c72369353e2864213304a1c5f83623a91570b..7cfa04f6233fd54ef4d59a83901473d4f4531017 100644 (file)
@@ -62,6 +62,7 @@ _a < _b ? _a : _b; })
 #include <gst/video/videooverlay.h>
 #include <unistd.h>
 #include <time.h>
+#include <stream_infer_common_util.h>
 
 #define WIDTH  (480)
 #define HEIGHT (270)
@@ -466,38 +467,54 @@ run_pose (void *user_data)
 static gboolean
 run_hand (void *user_data)
 {
-       HandOffData *udata = (HandOffData *)user_data;
-       if (!GST_IS_BUFFER(udata->buffer))
-               return FALSE;
+       while (1) {
+               // We should guerantee a new camera buffer not to be pushed to stack
+               // until latest camera buffer in the stack is popped and copied
+               // to mv_src_p.
+               g_mutex_lock(&pose_mutex);
 
-       GstMapInfo map;
+               user_stack_t *s = PopBuffer();
+               if (s == NULL) {
+                       g_mutex_unlock(&pose_mutex);
+                       usleep(10);
+                       continue;
+               }
 
-       gst_buffer_map(udata->buffer, &map, GST_MAP_READ);
+               if (!GST_IS_BUFFER((GstBuffer *)s->buffer)) {
+                       g_mutex_unlock(&pose_mutex);
+                       usleep(10);
+                       continue;
+               }
 
-       mv_source_clear(mv_src_p);
+               GstMapInfo map;
 
-       mv_source_fill_by_buffer(mv_src_p, map.data, 224*224*3, 224, 224, MEDIA_VISION_COLORSPACE_RGB888);
+               gst_buffer_map((GstBuffer *)s->buffer, &map, GST_MAP_READ);
 
-       gst_buffer_unmap(udata->buffer, &map);
+               mv_source_clear(mv_src_p);
 
+               mv_source_fill_by_buffer(mv_src_p, map.data, 224*224*3, 224, 224, MEDIA_VISION_COLORSPACE_RGB888);
 
-       struct timespec s_tspec;
-       struct timespec e_tspec;
+               gst_buffer_unmap((GstBuffer *)s->buffer, &map);
 
-       void * outputTensorBuffer = (void*)udata->user_data;
+               g_mutex_unlock(&pose_mutex);
 
-       clock_gettime(CLOCK_MONOTONIC, &s_tspec);
+               struct timespec s_tspec;
+               struct timespec e_tspec;
 
-       // invoke tflite -> _hand_detected_cb -> memcpy output -> invoke tflite -> _pose_cb
-       mv_inference_hand_detect(mv_src_p, hp_mv_infer, _hand_detected_cb, outputTensorBuffer);
+               void *outputTensorBuffer = s->user_data;
 
-       clock_gettime(CLOCK_MONOTONIC, &e_tspec);
-       struct timespec diffspec = diff(s_tspec, e_tspec);
-       unsigned long timeDiff = gettotalmillisec(diffspec);
-       printf("detect + pose time: %lu(ms)\n", timeDiff);
+               clock_gettime(CLOCK_MONOTONIC, &s_tspec);
 
-       return FALSE;
+               // invoke tflite -> _hand_detected_cb -> memcpy output -> invoke tflite -> _pose_cb
+               mv_inference_hand_detect(mv_src_p, hp_mv_infer, _hand_detected_cb, outputTensorBuffer);
 
+               clock_gettime(CLOCK_MONOTONIC, &e_tspec);
+               struct timespec diffspec = diff(s_tspec, e_tspec);
+               unsigned long timeDiff = gettotalmillisec(diffspec);
+               printf("detect + pose time: %lu(ms)\n", timeDiff);
+       }
+
+       return FALSE;
 }
 
 static void
@@ -524,25 +541,16 @@ _pose_est_handoff(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer u
 static void
 _hand_est_handoff(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer user_data)
 {
-
        nFrames++;
-       hdata_p.buffer = buffer;
-       hdata_p.user_data = user_data;
+       user_stack_t *s = GetNewStack();
+       s->buffer = buffer;
+       s->user_data = user_data;
 
-#if 0
-       if (nFrames % 15 == 0) {
-               g_mutex_lock(&pose_mutex);
-               g_idle_add (run_hand, &hdata_p);
-               g_mutex_unlock(&pose_mutex);
-       }
-#else
        g_mutex_lock(&pose_mutex);
-       g_idle_add (run_hand, &hdata_p);
+       PushBuffer(s);
        g_mutex_unlock(&pose_mutex);
-#endif
 }
 
-
 static void
 prepare_overlay (GstElement * overlay, GstCaps * caps, gpointer user_data)
 {
@@ -645,7 +653,6 @@ draw_overlay_hand (GstElement * overlay, cairo_t * cr, guint64 timestamp,
                return;
        }
 
-
        cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.7);
        cairo_set_line_width(cr, 2.0);
 
@@ -699,8 +706,6 @@ draw_overlay_hand (GstElement * overlay, cairo_t * cr, guint64 timestamp,
                cairo_line_to(cr, humanSkeleton.pose[k].x, humanSkeleton.pose[k].y);
        }
        cairo_stroke(cr);
-
-
 }
 
 static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
@@ -1410,6 +1415,8 @@ static int app_create(void *data)
        appdata *ad = data;
        Evas_Object *win = NULL;
 
+       InitProfiler();
+
        // GST
        g_mutex_init(&pose_mutex);
 
@@ -1646,6 +1653,7 @@ static int app_create(void *data)
        if (ad->modelType == MODEL_TYPE_POSE_CPM) {
                handler_p = g_signal_connect (vrsink, "handoff", G_CALLBACK(_pose_est_handoff), NULL);
        } else {
+               g_idle_add (run_hand, NULL);
                handler_p = g_signal_connect (vrsink, "handoff", G_CALLBACK(_hand_est_handoff), outputTensorData);
        }
 
@@ -1748,6 +1756,7 @@ static int app_create(void *data)
 #else
        gst_element_set_state (pipeline, GST_STATE_PLAYING);
 #endif
+
        return 0;
 }
 
@@ -1757,6 +1766,8 @@ static int app_terminate(void *data)
        appdata *ad = data;
        int i = 0;
 
+       DeinitProfiler();
+
        /* out of loop */
        printf(TEXT_GREEN "Stopping.....\n" TEXT_RESET);
        gst_element_set_state(pipeline, GST_STATE_NULL);
diff --git a/test/testsuites/stream_infer/stream_infer_common_util.c b/test/testsuites/stream_infer/stream_infer_common_util.c
new file mode 100644 (file)
index 0000000..8dd72b1
--- /dev/null
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <stream_infer_common_util.h>
+
+#define DUMP_FILE_NAME "latency.txt"
+#define NANO_PER_SEC ((__clock_t) 1000000000)
+#define NANO_PER_MILLI  ((__clock_t) 1000000)
+#define MILLI_PER_SEC  ((__clock_t) 1000)
+#define MAX_MSG_LEN            256
+#define MAX_STACK_SIZE 50
+
+typedef struct {
+       char msg[MAX_MSG_LEN];
+       struct timespec startTime;
+       struct timespec endTime;
+} message_t;
+
+static FILE *gFile;
+
+static struct timespec GetTimeDiff(const struct timespec *start,
+                                                                  const struct timespec *end)
+{
+       struct timespec temp;
+
+       if ((end->tv_nsec - start->tv_nsec) < 0) {
+               temp.tv_sec = end->tv_sec - start->tv_sec - 1;
+               temp.tv_nsec = NANO_PER_SEC + end->tv_nsec - start->tv_nsec;
+       }
+       else {
+               temp.tv_sec = end->tv_sec - start->tv_sec;
+               temp.tv_nsec = end->tv_nsec - start->tv_nsec;
+       }
+
+       return temp;
+}
+
+static unsigned long ConvertMillisec(const struct timespec time)
+{
+       return (unsigned long)(time.tv_sec * MILLI_PER_SEC + time.tv_nsec / NANO_PER_MILLI);
+}
+
+void InitProfiler(void)
+{
+       gFile = fopen(DUMP_FILE_NAME, "a+");
+}
+
+void *StartProfiler(const char *msg)
+{
+       message_t *message = malloc(sizeof(message_t));
+       memset((void *)message, 0, sizeof(message_t));
+       clock_gettime(CLOCK_MONOTONIC, &message->startTime);
+       strncpy(message->msg, msg, strlen(msg));
+
+       return (void *)message;
+}
+
+void StopProfiler(void *handle)
+{
+       message_t *message = (message_t *)handle;
+
+       clock_gettime(CLOCK_MONOTONIC, &message->endTime);
+       unsigned long elapsed_time = ConvertMillisec(GetTimeDiff(&message->startTime, &message->endTime));
+
+       char sMessage[MAX_MSG_LEN] = { 0, };
+       sprintf(sMessage, "%s ==> %lums\n", message->msg, elapsed_time);
+       fwrite((void *)sMessage, MAX_MSG_LEN, 1, gFile);
+
+       free(message);
+}
+
+void DeinitProfiler(void)
+{
+       if (gFile)
+               fclose(gFile);
+}
+
+static user_stack_t FREE_STACK[MAX_STACK_SIZE * 2], *STACK[MAX_STACK_SIZE];
+static int s_cnt, down_s, top_s;
+
+user_stack_t *GetNewStack(void)
+{
+       if (s_cnt == (MAX_STACK_SIZE * 2))
+               s_cnt = 0;
+
+       return &FREE_STACK[s_cnt++];
+}
+
+void PushBuffer(user_stack_t *data)
+{
+       if (top_s == MAX_STACK_SIZE) {
+               top_s = down_s;
+       }
+
+       STACK[top_s++] = data;
+}
+
+user_stack_t *PopBuffer(void)
+{
+       if (down_s == top_s) {
+               // there must be no case.
+               return NULL;
+       }
+
+       user_stack_t *data = STACK[--top_s];
+
+       return data;
+}
diff --git a/test/testsuites/stream_infer/stream_infer_common_util.h b/test/testsuites/stream_infer/stream_infer_common_util.h
new file mode 100644 (file)
index 0000000..b1b44c0
--- /dev/null
@@ -0,0 +1,13 @@
+typedef struct STACK {
+       void *buffer;
+       void *user_data;
+} user_stack_t;
+
+void InitProfiler(void);
+void *StartProfiler(const char *msg);
+void StopProfiler(void *handle);
+void DeinitProfiler();
+
+user_stack_t *GetNewStack(void);
+void PushBuffer(user_stack_t *data);
+user_stack_t *PopBuffer(void);