From: Sangchul Lee Date: Mon, 30 Nov 2020 07:29:04 +0000 (+0900) Subject: webrtc_tbm: Add internal functions regarding TBM buffer X-Git-Tag: submit/tizen/20210729.023123~178 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F82%2F248582%2F14;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_tbm: Add internal functions regarding TBM buffer 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 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 63b37530..c302a4fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/include/webrtc_private.h b/include/webrtc_private.h index dc5087c9..edf92338 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -26,6 +26,7 @@ #endif #include #include +#include #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); diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index 837b3f0b..e13982c5 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -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 index 00000000..08374e9b --- /dev/null +++ b/src/webrtc_tbm.c @@ -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); +}