webrtc_tbm: Add internal functions regarding TBM buffer 82/248582/14
authorSangchul Lee <sc11.lee@samsung.com>
Mon, 30 Nov 2020 07:29:04 +0000 (16:29 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 9 Dec 2020 04:01:48 +0000 (13:01 +0900)
It'll be used for video rendering pipeline of EVAS surface
without zerocopy format.

[Version] 0.1.64
[Issue Type] New feature

Change-Id: I15377253173684f86bc770f3bea717507fcc8f3b
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
CMakeLists.txt
include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc_tbm.c [new file with mode: 0644]

index 63b375306d1b7524eedaa3fba28d2c0a77e6845f..c302a4fb46f82fd0a79b753b62e2969220b17333 100644 (file)
@@ -11,7 +11,7 @@ SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib")
 SET(INC_DIR include)
 INCLUDE_DIRECTORIES(${INC_DIR})
 
-SET(dependents "dlog glib-2.0 gstreamer-1.0 gstreamer-webrtc-1.0 json-glib-1.0 iniparser mm-common mm-display-interface")
+SET(dependents "dlog glib-2.0 gstreamer-1.0 gstreamer-webrtc-1.0 json-glib-1.0 iniparser mm-common mm-display-interface libtbm")
 SET(pc_dependents "capi-base-common" )
 
 INCLUDE(FindPkgConfig)
index dc5087c91f3039cd613f40efa905605064ba867d..edf9233843ec7f0dc8a575a12388e035dc594bd8 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 #include <iniparser.h>
 #include <mm_display_interface.h>
+#include <tbm_bufmgr.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -97,6 +98,15 @@ do { \
        } \
 } while (0)
 
+#define RET_WITH_UNLOCK_IF(expr, mutex, fmt, arg...) \
+do { \
+       if ((expr)) { \
+               LOG_ERROR(""fmt"", ##arg); \
+               g_mutex_unlock(mutex); \
+               return; \
+       } \
+} while (0)
+
 #define RET_VAL_WITH_UNLOCK_IF(expr, val, mutex, fmt, arg...) \
 do { \
        if ((expr)) { \
@@ -200,6 +210,19 @@ typedef struct _webrtc_callbacks {
        void *user_data;
 } webrtc_callbacks_s;
 
+typedef struct _webrtc_tbm_bo_s {
+       bool used;
+       void *bo;
+} webrtc_tbm_bo_s;
+
+typedef struct _webrtc_tbm_s {
+       tbm_bufmgr bufmgr;
+
+       GCond cond;
+       GMutex mutex;
+       GList *bo_list;    /* for decoded video data by sw codec */
+} webrtc_tbm_s;
+
 typedef struct _webrtc_display {
        void *object;
        int type;
@@ -314,6 +337,13 @@ void _init_display(webrtc_s *webrtc);
 void _deinit_display(webrtc_s *webrtc);
 int _apply_display(webrtc_s *webrtc, webrtc_display_s *display);
 
+webrtc_tbm_s *_alloc_tbm(void);
+void _release_tbm(webrtc_tbm_s *tbm);
+void _create_tbm_bo_list(webrtc_tbm_s *tbm, int bo_size, int list_length);
+void _destroy_tbm_bo_list(webrtc_tbm_s *tbm);
+void *_get_unused_tbm_bo(webrtc_tbm_s *tbm, unsigned int timeout_sec);
+void _release_tbm_bo(webrtc_tbm_s *tbm, void *bo);
+
 int _webrtcbin_create_offer(webrtc_s *webrtc, char **offer);
 int _webrtcbin_create_answer(webrtc_s *webrtc, char **answer);
 int _webrtcbin_set_session_description(webrtc_s *webrtc, const char *description, bool is_remote);
index 837b3f0b0587d98c74e14f6e27e1417d89253fe8..e13982c5fc524b3153321969b80b6be31251411f 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.1.63
+Version:    0.1.64
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -20,6 +20,7 @@ BuildRequires:  pkgconfig(libsoup-2.4)
 BuildRequires:  pkgconfig(iniparser)
 BuildRequires:  pkgconfig(mm-display-interface)
 BuildRequires:  pkgconfig(mm-common)
+BuildRequires:  pkgconfig(libtbm)
 
 %description
 A WebRTC library in Tizen Native API.
diff --git a/src/webrtc_tbm.c b/src/webrtc_tbm.c
new file mode 100644 (file)
index 0000000..08374e9
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "webrtc.h"
+#include "webrtc_private.h"
+
+static void __tbm_bo_destroy_cb(webrtc_tbm_bo_s *tbm_bo)
+{
+       if (tbm_bo == NULL)
+               return;
+
+       if (tbm_bo->bo && tbm_bo->used) {
+               tbm_bo->used = false;
+               LOG_DEBUG("unref bo[%p]", tbm_bo->bo);
+               tbm_bo_unref(tbm_bo->bo);
+               tbm_bo->bo = NULL;
+       }
+
+       g_free(tbm_bo);
+}
+
+void _destroy_tbm_bo_list(webrtc_tbm_s *tbm)
+{
+       RET_IF(tbm == NULL, "tbm is NULL");
+
+       g_mutex_lock(&tbm->mutex);
+
+       if (tbm->bo_list) {
+               LOG_DEBUG("destroy tbm->bo_list[%p, length:%d]", tbm->bo_list, g_list_length(tbm->bo_list));
+               g_list_free_full(tbm->bo_list, (GDestroyNotify)__tbm_bo_destroy_cb);
+               tbm->bo_list = NULL;
+       }
+
+       g_mutex_unlock(&tbm->mutex);
+}
+
+void _create_tbm_bo_list(webrtc_tbm_s *tbm, int bo_size, int list_length)
+{
+       RET_IF(tbm == NULL, "tbm is NULL");
+       RET_IF(bo_size <= 0, "invalid bo_size(%d)", bo_size);
+       RET_IF(list_length <= 0, "invalid list_length(%d)", list_length);
+
+       g_mutex_lock(&tbm->mutex);
+
+       RET_WITH_UNLOCK_IF(tbm->bo_list != NULL, &tbm->mutex, "bo_list is not NULL");
+
+       while (list_length--) {
+               webrtc_tbm_bo_s *tbm_bo = g_new0(webrtc_tbm_bo_s, 1);
+
+               tbm_bo->bo = tbm_bo_alloc(tbm->bufmgr, bo_size, TBM_BO_DEFAULT);
+               if (tbm_bo->bo == NULL) {
+                       LOG_ERROR("failed to tbm_bo_alloc()");
+                       g_free(tbm_bo);
+                       break;
+               }
+               LOG_DEBUG("bo[%p] is created", tbm_bo->bo);
+               tbm->bo_list = g_list_append(tbm->bo_list, tbm_bo);
+       }
+       LOG_DEBUG("tbm->bo_list[%p, length:%d] is created", tbm->bo_list, g_list_length(tbm->bo_list));
+
+       g_mutex_unlock(&tbm->mutex);
+}
+
+void *_get_unused_tbm_bo(webrtc_tbm_s *tbm, unsigned int timeout_sec)
+{
+       GList *l;
+       gboolean ret = TRUE;
+       gint64 end_time = g_get_monotonic_time() + timeout_sec * G_TIME_SPAN_SECOND;
+
+       RET_VAL_IF(tbm == NULL, NULL, "tbm is NULL");
+
+       g_mutex_lock(&tbm->mutex);
+
+       while (true) {
+               for (l = g_list_first(tbm->bo_list); l; l = g_list_next(l)) {
+                       webrtc_tbm_bo_s *tbm_bo = (webrtc_tbm_bo_s *)l->data;
+                       if (tbm_bo && (!tbm_bo->used)) {
+                               LOG_DEBUG("found unused bo[%p]", tbm_bo->bo);
+                               tbm_bo->used = true;
+                               g_mutex_unlock(&tbm->mutex);
+                               return tbm_bo_ref(tbm_bo->bo);
+                       }
+               }
+
+               ret = g_cond_wait_until(&tbm->cond, &tbm->mutex, end_time);
+               if (!ret) {
+                       LOGE("failed to get unused bo within %d sec. of timeout", timeout_sec);
+                       break;
+               }
+       }
+
+       g_mutex_unlock(&tbm->mutex);
+
+       return NULL;
+}
+
+void _release_tbm_bo(webrtc_tbm_s *tbm, void *bo)
+{
+       GList *l;
+
+       RET_IF(tbm == NULL, "tbm is NUL");
+       RET_IF(bo == NULL, "bo is NUL");
+
+       g_mutex_lock(&tbm->mutex);
+
+       for (l = g_list_first(tbm->bo_list); l; l = g_list_next(l)) {
+               webrtc_tbm_bo_s *tbm_bo = (webrtc_tbm_bo_s *)l->data;
+               if (tbm_bo && (tbm_bo->bo == bo)) {
+                       tbm_bo->used = false;
+                       LOG_DEBUG("unref bo[%p]", tbm_bo->bo);
+                       tbm_bo_unref(tbm_bo->bo);
+                       g_cond_signal(&tbm->cond);
+                       g_mutex_unlock(&tbm->mutex);
+                       return;
+               }
+       }
+
+       g_mutex_unlock(&tbm->mutex);
+}
+
+webrtc_tbm_s *_alloc_tbm(void)
+{
+       webrtc_tbm_s *tbm = g_new0(webrtc_tbm_s, 1);
+
+       tbm->bufmgr = tbm_bufmgr_init(-1);
+       if (tbm->bufmgr == NULL) {
+               LOG_ERROR("tbm->bufmgr is NULL");
+               g_free(tbm);
+               return NULL;
+       }
+
+       g_mutex_init(&tbm->mutex);
+       g_cond_init(&tbm->cond);
+
+       LOG_DEBUG("tbm[%p] bufmgr[%p]", tbm, tbm->bufmgr);
+
+       return tbm;
+}
+
+void _release_tbm(webrtc_tbm_s *tbm)
+{
+       RET_IF(tbm == NULL, "tbm is NULL");
+
+       _destroy_tbm_bo_list(tbm);
+
+       g_mutex_lock(&tbm->mutex);
+
+       if (tbm->bufmgr) {
+               LOG_DEBUG("deinit tbm->bufmgr[%p]", tbm->bufmgr);
+               tbm_bufmgr_deinit(tbm->bufmgr);
+               tbm->bufmgr = NULL;
+       }
+
+       g_mutex_unlock(&tbm->mutex);
+       g_mutex_clear(&tbm->mutex);
+       g_cond_clear(&tbm->cond);
+
+       LOG_DEBUG("free tbm[%p]", tbm);
+
+       g_free(tbm);
+}