/ext/nnstreamer/android_source/gstamcsrc_looper.cc

https://github.com/nnstreamer/nnstreamer · C++ · 257 lines · 145 code · 37 blank · 75 comment · 12 complexity · a8153091ff46bfe12414e36e80d934bc MD5 · raw file

  1. /**
  2. * GStreamer Android MediaCodec (AMC) Source Looper
  3. * Copyright (C) 2019 Samsung Electronics Co., Ltd. All rights reserved.
  4. * Copyright (C) 2019 Dongju Chae <dongju.chae@samsung.com>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Library General Public
  8. * License as published by the Free Software Foundation;
  9. * version 2.1 of the License.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Library General Public License for more details.
  15. *
  16. */
  17. /**
  18. * @file gstamcsrc_looper.cc
  19. * @date 19 May 2019
  20. * @brief A looper thread to perform event messages between amcsrc and media codec
  21. * @see http://github.com/nnstreamer/nnstreamer
  22. * @author Dongju Chae <dongju.chae@samsung.com>
  23. * @bug No known bugs except for NYI items
  24. */
  25. #include "gstamcsrc_looper.h"
  26. #include "gstamcsrc.h"
  27. #include <errno.h>
  28. #include <fcntl.h>
  29. #include <jni.h>
  30. #include <limits.h>
  31. #include <pthread.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <sys/stat.h>
  35. #include <sys/types.h>
  36. #include <unistd.h>
  37. #include <android/log.h>
  38. #define TAG "AMCSRC-looper"
  39. #define LOG(...) __android_log_print (ANDROID_LOG_INFO, TAG, __VA_ARGS__)
  40. /**
  41. * @brief Looper constructor
  42. */
  43. Looper::Looper ()
  44. {
  45. head = NULL;
  46. running = FALSE;
  47. num_msg = 0;
  48. handle = NULL;
  49. pthread_mutex_init (&mutex, NULL);
  50. pthread_cond_init (&cond, NULL);
  51. }
  52. /**
  53. * @brief Looper desctructor
  54. */
  55. Looper::~Looper ()
  56. {
  57. flush_msg ();
  58. pthread_mutex_destroy (&mutex);
  59. pthread_cond_destroy (&cond);
  60. }
  61. /**
  62. * @brief Creates a looper thread
  63. */
  64. void
  65. Looper::start (void)
  66. {
  67. pthread_attr_t attr;
  68. pthread_attr_init (&attr);
  69. pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
  70. pthread_create (&thread, &attr, entry, this);
  71. pthread_attr_destroy (&attr);
  72. }
  73. /**
  74. * @brief allocate a message with arguments
  75. * @param[in] cmd command type
  76. * @param[in] data argument
  77. * @param[in] flush whether flushing the pending messages
  78. */
  79. void
  80. Looper::post (gint cmd, void *data, bool flush)
  81. {
  82. looper_message *msg = new looper_message ();
  83. msg->cmd = cmd;
  84. msg->data = data;
  85. msg->next = NULL;
  86. add_msg (msg, flush);
  87. }
  88. /**
  89. * @brief append a message
  90. * @param[in] new_msg new message to append
  91. * @param[in] flush whether flushing the pending messages
  92. */
  93. void
  94. Looper::add_msg (looper_message *new_msg, bool flush)
  95. {
  96. looper_message *msg;
  97. pthread_mutex_lock (&mutex);
  98. /** Flush old pending messages */
  99. if (flush) {
  100. flush_msg ();
  101. }
  102. /** Append new message */
  103. if (head) {
  104. msg = head;
  105. while (msg->next)
  106. msg = msg->next;
  107. msg->next = new_msg;
  108. } else
  109. head = new_msg;
  110. num_msg++;
  111. pthread_cond_broadcast (&cond);
  112. pthread_mutex_unlock (&mutex);
  113. }
  114. /**
  115. * @brief Flush all messages.
  116. */
  117. void
  118. Looper::flush_msg (void)
  119. {
  120. looper_message *msg;
  121. msg = head;
  122. while (msg) {
  123. head = msg->next;
  124. delete msg;
  125. msg = head;
  126. }
  127. head = NULL;
  128. num_msg = 0;
  129. }
  130. /**
  131. * @brief looper's entry function
  132. */
  133. void *
  134. Looper::entry (void *data)
  135. {
  136. if (data)
  137. ((Looper *) data)->loop ();
  138. return NULL;
  139. }
  140. /**
  141. * @brief looper's loop function
  142. */
  143. void
  144. Looper::loop (void)
  145. {
  146. LOG ("AMC looper started!");
  147. running = TRUE;
  148. while (running) {
  149. looper_message *msg;
  150. /** Wait new message */
  151. pthread_mutex_lock (&mutex);
  152. while (!(num_msg > 0)) {
  153. pthread_cond_wait (&cond, &mutex);
  154. }
  155. msg = head;
  156. head = head->next;
  157. num_msg--;
  158. pthread_mutex_unlock (&mutex);
  159. if (handle)
  160. handle (msg->cmd, msg->data);
  161. delete msg;
  162. }
  163. LOG ("Looper terminated");
  164. }
  165. /**
  166. * @brief looper's exit function
  167. */
  168. void
  169. Looper::exit (void)
  170. {
  171. running = FALSE;
  172. post (0, NULL, TRUE);
  173. /* 0 == MSG_0 */
  174. }
  175. /**
  176. * @brief C-wrapper for Looper constructor
  177. */
  178. void *
  179. Looper_new (void)
  180. {
  181. Looper *looper = new Looper ();
  182. looper->start ();
  183. return looper;
  184. }
  185. /**
  186. * @brief C-wrapper for Looper destructor
  187. */
  188. void
  189. Looper_delete (void *looper)
  190. {
  191. if (looper)
  192. delete ((Looper *) looper);
  193. }
  194. /**
  195. * @brief C-wrapper for Looper post function
  196. */
  197. void
  198. Looper_post (void *looper, gint cmd, void *data, gboolean flush)
  199. {
  200. if (looper)
  201. ((Looper *) looper)->post (cmd, data, flush);
  202. }
  203. /**
  204. * @brief C-wrapper for setting handle function of looper
  205. */
  206. void
  207. Looper_set_handle (void *looper, void (*handle) (gint, void *))
  208. {
  209. if (looper)
  210. ((Looper *) looper)->handle = handle;
  211. }
  212. /**
  213. * @brief C-wrapper for terminating the looper
  214. */
  215. void
  216. Looper_exit (void *looper)
  217. {
  218. if (looper)
  219. ((Looper *) looper)->exit ();
  220. }