g_free(caps_str); \
} while (0)
+#define APPEND_ELEMENT(x_list, x_element) \
+do { \
+ if (!(x_element)) \
+ break; \
+ x_list = g_list_append(x_list, x_element); \
+ LOG_DEBUG("%s is appended", GST_ELEMENT_NAME(x_element)); \
+} while (0)
+
+#define PREPEND_ELEMENT(x_list, x_element) \
+do { \
+ if (!(x_element)) \
+ break; \
+ x_list = g_list_prepend(x_list, x_element); \
+ LOG_DEBUG("%s is prepended", GST_ELEMENT_NAME(x_element)); \
+} while (0)
+
#define CREATE_ELEMENT_FROM_REGISTRY(x_elem_info, x_klass_name, x_sink_caps, x_src_caps, x_excluded_elements, x_element) \
do { \
x_elem_info.klass_name = x_klass_name; \
int _gst_build_pipeline(webrtc_s *webrtc);
void _gst_destroy_pipeline(webrtc_s *webrtc);
int _gst_pipeline_set_state(webrtc_s *webrtc, GstState state);
+bool _sync_elements_state_with_parent(GList *element_list);
+bool _add_elements_to_bin(GstBin *bin, GList *element_list);
+bool _link_elements(GList *element_list);
+bool _remove_elements_from_bin(GstBin *bin, GList *element_list);
void _gst_set_element_properties(GstElement *element, GStrv key_value_pairs);
int _add_media_source(webrtc_s *webrtc, int type, unsigned int *source_id);
int _add_media_source_internal(webrtc_s *webrtc, int type, unsigned int *source_id);
#include "webrtc_private.h"
#include <gst/audio/audio.h>
-#define APPEND_ELEMENT(x_list, x_element) \
-do { \
- if (!(x_element)) \
- break; \
- x_list = g_list_append(x_list, x_element); \
- LOG_DEBUG("%s is appended", GST_ELEMENT_NAME(x_element)); \
-} while (0)
-
-#define PREPEND_ELEMENT(x_list, x_element) \
-do { \
- if (!(x_element)) \
- break; \
- x_list = g_list_prepend(x_list, x_element); \
- LOG_DEBUG("%s is prepended", GST_ELEMENT_NAME(x_element)); \
-} while (0)
-
#define GET_AV_IDX_BY_TYPE(x_media_type) GET_AV_IDX(x_media_type == MEDIA_TYPE_AUDIO)
#define GST_KLASS_NAME_ENCODER_AUDIO "Codec/Encoder/Audio"
const char *_get_source_element(webrtc_s *webrtc, int type);
GstElement *_find_element_in_bin(GstBin *bin, const gchar *name);
bool _is_hw_encoder_used(webrtc_s *webrtc, webrtc_media_source_type_e source_type, media_type_e media_type);
-bool _add_elements_to_bin(GstBin *bin, GList *element_list);
-bool _link_elements(GList *element_list);
-bool _remove_elements_from_bin(GstBin *bin, GList *element_list);
const char *_get_audio_media_type(const char *codec_name);
const char *_get_video_media_type(const char *codec_name);
GstAudioFormat _get_gst_audio_raw_format_from_string(const char *format);
Name: capi-media-webrtc
Summary: A WebRTC library in Tizen Native API
-Version: 0.3.147
+Version: 0.3.148
Release: 0
Group: Multimedia/API
License: Apache-2.0
return WEBRTC_ERROR_NONE;
}
+bool _sync_elements_state_with_parent(GList *element_list)
+{
+ GList *list;
+
+ RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
+
+ for (list = element_list; list; list = g_list_next(list))
+ RET_VAL_IF(!gst_element_sync_state_with_parent((GstElement *)list->data), false,
+ "failed to gst_element_sync_state_with_parent(), [%s]", GST_ELEMENT_NAME((GstElement *)list->data));
+
+ return true;
+}
+
+static void __foreach_unref_object_cb(gpointer data, gpointer user_data)
+{
+ GstElement *element = (GstElement *)data;
+
+ LOG_DEBUG("%s is unreferenced", GST_ELEMENT_NAME(element));
+ SAFE_GST_OBJECT_UNREF(element);
+}
+
+bool _add_elements_to_bin(GstBin *bin, GList *element_list)
+{
+ GstElement *element;
+ GList *list;
+ GList *added_list = NULL;
+
+ RET_VAL_IF(bin == NULL, false, "bin is NULL");
+ RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
+
+ for (list = element_list; list; list = list->next) {
+ element = (GstElement *)list->data;
+ if (!gst_bin_add(bin, element)) {
+ LOG_ERROR("failed to gst_bin_add(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
+ _remove_elements_from_bin(bin, added_list);
+ SAFE_G_LIST_FREE(added_list);
+ g_list_foreach(list, __foreach_unref_object_cb, NULL); /* rest of elements on the list should be unreferenced */
+ return false;
+ }
+ APPEND_ELEMENT(added_list, element);
+ }
+
+ LOG_DEBUG("%d elements are added to bin[%s]", g_list_length(added_list), GST_ELEMENT_NAME(bin));
+
+ SAFE_G_LIST_FREE(added_list);
+
+ return true;
+}
+
+bool _link_elements(GList *element_list)
+{
+ GstElement *curr;
+ GstElement *prev = NULL;
+ GList *list;
+ int count = 0;
+
+ RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
+
+ for (list = element_list; list; list = g_list_next(list)) {
+ if (!g_list_previous(list))
+ continue;
+ prev = (GstElement *)(g_list_previous(list)->data);
+ curr = (GstElement *)list->data;
+ RET_VAL_IF(!gst_element_link(prev, curr), false,
+ "failed to gst_element_link(), [%s] - [%s]", GST_ELEMENT_NAME(prev), GST_ELEMENT_NAME(curr));
+ LOG_WARNING("[%s] - [%s]", GST_ELEMENT_NAME(prev), GST_ELEMENT_NAME(curr));
+ count++;
+ }
+
+ LOG_DEBUG("%d elements are linked", count);
+
+ return true;
+}
+
+//LCOV_EXCL_START
+bool _remove_elements_from_bin(GstBin *bin, GList *element_list)
+{
+ GstElement *element;
+ GList *list;
+ int count = 0;
+
+ RET_VAL_IF(bin == NULL, false, "bin is NULL");
+ RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
+
+ for (list = element_list; list; list = g_list_next(list)) {
+ element = (GstElement *)list->data;
+ RET_VAL_IF(!gst_bin_remove(bin, element), false,
+ "failed to gst_bin_remove(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
+ count++;
+ }
+
+ LOG_DEBUG("%d elements are removed from bin[%s]", count, GST_ELEMENT_NAME(bin));
+
+ return true;
+}
+//LCOV_EXCL_STOP
+
static void __parse_type_and_set_value(GType type, GstElement *element, GStrv key_value_pair)
{
RET_IF(element == NULL, "element is NULL");
static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *src_pad)
{
webrtc_gst_slot_s *sink;
- GstElement *videoconvert;
+ GstElement *videoconvert = NULL;
GstElement *videosink;
+ GstElement *link_to;
const char *videosink_factory_name;
+ GList *element_list = NULL;
bool display_is_set;
int ret = WEBRTC_ERROR_NONE;
g_autoptr(GMutexLocker) locker = NULL;
RET_VAL_IF(sink == NULL, WEBRTC_ERROR_INVALID_OPERATION, "could not find an item by [%s] in sink slots", GST_ELEMENT_NAME(decodebin));
RET_VAL_IF(sink->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- sink->media_types = MEDIA_TYPE_VIDEO;
+ RET_VAL_IF((videosink_factory_name = __get_videosink_factory_name(sink->display, &webrtc->ini)) == NULL,
+ WEBRTC_ERROR_INVALID_OPERATION, "could not get videosink factory name");
+ sink->media_types = MEDIA_TYPE_VIDEO;
display_is_set = !!sink->display;
- if (!(videosink_factory_name = __get_videosink_factory_name(sink->display, &webrtc->ini)))
- return WEBRTC_ERROR_INVALID_OPERATION;
-
if (!(videosink = _create_element(videosink_factory_name, NULL)))
return WEBRTC_ERROR_INVALID_OPERATION;
+ APPEND_ELEMENT(element_list, videosink);
+ link_to = videosink;
if (display_is_set) {
locker = g_mutex_locker_new(&sink->display->mutex);
-
#ifndef TIZEN_TV
if (sink->display->type == WEBRTC_DISPLAY_TYPE_OVERLAY && webrtc->ini.resource_acquisition.video_overlay) {
if ((ret = _acquire_resource_for_type(webrtc, MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY)))
return ret;
}
#endif
+ if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL)))
+ goto exit;
+ PREPEND_ELEMENT(element_list, videoconvert);
+ link_to = videoconvert;
+
if (sink->display->type == WEBRTC_DISPLAY_TYPE_OVERLAY ||
sink->display->type == WEBRTC_DISPLAY_TYPE_ECORE_WL) {
gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(videosink), sink->display->overlay_surface_id);
NULL);
_connect_and_append_signal(&sink->signals, (GObject *)videosink, "handoff", G_CALLBACK(_video_stream_decoded_cb), sink->display);
}
+ }
- if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL)))
- return WEBRTC_ERROR_INVALID_OPERATION;
+ if (!_add_elements_to_bin(sink->bin, element_list)) {
+ SAFE_G_LIST_FREE(element_list);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
- gst_bin_add_many(sink->bin, videoconvert, videosink, NULL);
+ if (!_link_elements(element_list))
+ goto exit_with_remove_from_bin;
- if (!gst_element_sync_state_with_parent(videoconvert)) {
- LOG_ERROR("failed to gst_element_sync_state_with_parent() for [%s]", GST_ELEMENT_NAME(videoconvert));
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
- if (!gst_element_sync_state_with_parent(videosink)) {
- LOG_ERROR("failed to gst_element_sync_state_with_parent() for [%s]", GST_ELEMENT_NAME(videosink));
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
+ if (!gst_element_link(decodebin, link_to)) {
+ LOG_ERROR("failed to gst_element_link(), [%s] - [%s]", GST_ELEMENT_NAME(decodebin), GST_ELEMENT_NAME(link_to));
+ goto exit_with_remove_from_bin;
+ }
- if (!gst_element_link_many(decodebin, videoconvert, videosink, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
+ if (!_sync_elements_state_with_parent(element_list))
+ goto exit_with_remove_from_bin;
+ if (display_is_set)
sink->display->sink_element = videosink;
- } else {
- gst_bin_add_many(sink->bin, videosink, NULL);
-
- if (!gst_element_sync_state_with_parent(videosink)) {
- LOG_ERROR("failed to gst_element_sync_state_with_parent() for [%s]", GST_ELEMENT_NAME(videosink));
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
+ SAFE_G_LIST_FREE(element_list);
- if (!gst_element_link_many(decodebin, videosink, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
- }
+ return WEBRTC_ERROR_NONE;
- return ret;
+exit_with_remove_from_bin:
+ _remove_elements_from_bin(sink->bin, element_list);
+ SAFE_G_LIST_FREE(element_list);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+exit:
+ SAFE_G_LIST_FREE_FULL(element_list, gst_object_unref);
+ return WEBRTC_ERROR_INVALID_OPERATION;
}
static int __build_audiosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *src_pad)
GstElement *audioconvert;
GstElement *audioresample;
GstElement *audiosink;
+ GstElement *link_to;
+ GList *element_list = NULL;
bool stream_info_is_set;
int ret = WEBRTC_ERROR_NONE;
RET_VAL_IF(sink->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
sink->media_types = MEDIA_TYPE_AUDIO;
-
stream_info_is_set = !!sink->sound_stream_info.type;
- if (stream_info_is_set) {
- if (!(audioconvert = _create_element(DEFAULT_ELEMENT_AUDIOCONVERT, NULL)))
- return WEBRTC_ERROR_INVALID_OPERATION;
-
- if (!(audioresample = _create_element(DEFAULT_ELEMENT_AUDIORESAMPLE, NULL)))
- return WEBRTC_ERROR_INVALID_OPERATION;
-
- if (!(audiosink = _create_element(webrtc->ini.rendering_sink.a_sink_element, NULL)))
- return WEBRTC_ERROR_INVALID_OPERATION;
+ if (!(audiosink = _create_element(stream_info_is_set ? webrtc->ini.rendering_sink.a_sink_element : DEFAULT_ELEMENT_FAKESINK, NULL)))
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ APPEND_ELEMENT(element_list, audiosink);
+ link_to = audiosink;
+ if (stream_info_is_set) {
if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(audiosink)), "stream-properties")) {
if (sink->sound_stream_info.type) {
ret = _apply_stream_info(audiosink, sink->sound_stream_info.type, sink->sound_stream_info.index,
SOUND_MANAGER_STREAM_NO_REFERENCE_DEVICE);
- if (ret != WEBRTC_ERROR_NONE) /* FIXME: unref all the created elements */
- return WEBRTC_ERROR_INVALID_OPERATION;
+ if (ret != WEBRTC_ERROR_NONE)
+ goto exit;
}
}
- gst_bin_add_many(sink->bin, audioconvert, audioresample, audiosink, NULL);
+ if (!(audioresample = _create_element(DEFAULT_ELEMENT_AUDIORESAMPLE, NULL)))
+ goto exit;
+ PREPEND_ELEMENT(element_list, audioresample);
- if (!gst_element_sync_state_with_parent(audioconvert)) {
- LOG_ERROR("failed to gst_element_sync_state_with_parent() for [%s]", GST_ELEMENT_NAME(audioconvert));
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
- if (!gst_element_sync_state_with_parent(audioresample)) {
- LOG_ERROR("failed to gst_element_sync_state_with_parent() for [%s]", GST_ELEMENT_NAME(audioresample));
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
- if (!gst_element_sync_state_with_parent(audiosink)) {
- LOG_ERROR("failed to gst_element_sync_state_with_parent() for [%s]", GST_ELEMENT_NAME(audiosink));
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
+ if (!(audioconvert = _create_element(DEFAULT_ELEMENT_AUDIOCONVERT, NULL)))
+ goto exit;
+ PREPEND_ELEMENT(element_list, audioconvert);
+ link_to = audioconvert;
+ }
- if (!gst_element_link_many(decodebin, audioconvert, audioresample, audiosink, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
+ if (!_add_elements_to_bin(sink->bin, element_list)) {
+ SAFE_G_LIST_FREE(element_list);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
- } else {
- LOG_WARNING("stream_info is not set, use [%s] to drop audio data", DEFAULT_ELEMENT_FAKESINK);
- if (!(audiosink = _create_element(DEFAULT_ELEMENT_FAKESINK, NULL)))
- return WEBRTC_ERROR_INVALID_OPERATION;
+ if (!_link_elements(element_list))
+ goto exit_with_remove_from_bin;
- gst_bin_add(sink->bin, audiosink);
+ if (!gst_element_link(decodebin, link_to)) {
+ LOG_ERROR("failed to gst_element_link(), [%s] - [%s]", GST_ELEMENT_NAME(decodebin), GST_ELEMENT_NAME(link_to));
+ goto exit_with_remove_from_bin;
+ }
- if (!gst_element_sync_state_with_parent(audiosink)) {
- LOG_ERROR("failed to gst_element_sync_state_with_parent() for [%s]", GST_ELEMENT_NAME(audiosink));
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
+ if (!_sync_elements_state_with_parent(element_list))
+ goto exit_with_remove_from_bin;
- if (!gst_element_link_many(decodebin, audiosink, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
- }
+ SAFE_G_LIST_FREE(element_list);
return WEBRTC_ERROR_NONE;
+
+exit_with_remove_from_bin:
+ _remove_elements_from_bin(sink->bin, element_list);
+ SAFE_G_LIST_FREE(element_list);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+exit:
+ SAFE_G_LIST_FREE_FULL(element_list, gst_object_unref);
+ return WEBRTC_ERROR_INVALID_OPERATION;
}
static unsigned int __get_id_from_name(const gchar *name)
source->av[idx].src_pad = NULL;
}
-static bool __sync_elements_state_with_parent(GList *element_list)
-{
- GList *list;
-
- RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
-
- for (list = element_list; list; list = g_list_next(list))
- RET_VAL_IF(!gst_element_sync_state_with_parent((GstElement *)list->data), false,
- "failed to gst_element_sync_state_with_parent(), [%s]", GST_ELEMENT_NAME((GstElement *)list->data));
-
- return true;
-}
-
static bool __link_switch_srcs(GstElement *switch_element, GList *switch_src_list)
{
GstElement *element;
if (!_link_elements(element_list))
goto exit_with_remove_from_bin;
- if (!__sync_elements_state_with_parent(element_list))
+ if (!_sync_elements_state_with_parent(element_list))
goto exit_with_remove_from_bin;
if (_set_ghost_pad_target(src_pad, capsfilter, true) != WEBRTC_ERROR_NONE)
if (!_link_elements(element_list))
goto exit_with_remove_from_bin;
- if (!__sync_elements_state_with_parent(element_list))
+ if (!_sync_elements_state_with_parent(element_list))
goto exit_with_remove_from_bin;
SAFE_G_LIST_FREE(element_list);
goto exit_with_remove_from_bin;
}
- if (!__sync_elements_state_with_parent(element_list))
+ if (!_sync_elements_state_with_parent(element_list))
goto exit_with_remove_from_bin;
SAFE_G_LIST_FREE(element_list);
goto exit_with_remove_from_bin;
}
- if (!__sync_elements_state_with_parent(element_list))
+ if (!_sync_elements_state_with_parent(element_list))
goto exit_with_remove_from_bin;
source->display->sink_element = videosink;
return false;
}
-static void __foreach_unref_object_cb(gpointer data, gpointer user_data)
-{
- GstElement *element = (GstElement *)data;
-
- LOG_DEBUG("%s is unreferenced", GST_ELEMENT_NAME(element));
- SAFE_GST_OBJECT_UNREF(element);
-}
-
-bool _add_elements_to_bin(GstBin *bin, GList *element_list)
-{
- GstElement *element;
- GList *list;
- GList *added_list = NULL;
-
- RET_VAL_IF(bin == NULL, false, "bin is NULL");
- RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
-
- for (list = element_list; list; list = list->next) {
- element = (GstElement *)list->data;
- if (!gst_bin_add(bin, element)) {
- LOG_ERROR("failed to gst_bin_add(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
- _remove_elements_from_bin(bin, added_list);
- SAFE_G_LIST_FREE(added_list);
- g_list_foreach(list, __foreach_unref_object_cb, NULL); /* rest of elements on the list should be unreferenced */
- return false;
- }
- APPEND_ELEMENT(added_list, element);
- }
-
- LOG_DEBUG("%d elements are added to bin[%s]", g_list_length(added_list), GST_ELEMENT_NAME(bin));
-
- SAFE_G_LIST_FREE(added_list);
-
- return true;
-}
-
-bool _link_elements(GList *element_list)
-{
- GstElement *curr;
- GstElement *prev = NULL;
- GList *list;
- int count = 0;
-
- RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
-
- for (list = element_list; list; list = g_list_next(list)) {
- if (!g_list_previous(list))
- continue;
- prev = (GstElement *)(g_list_previous(list)->data);
- curr = (GstElement *)list->data;
- RET_VAL_IF(!gst_element_link(prev, curr), false,
- "failed to gst_element_link(), [%s] - [%s]", GST_ELEMENT_NAME(prev), GST_ELEMENT_NAME(curr));
- LOG_WARNING("[%s] - [%s]", GST_ELEMENT_NAME(prev), GST_ELEMENT_NAME(curr));
- count++;
- }
-
- LOG_DEBUG("%d elements are linked", count);
-
- return true;
-}
-
-//LCOV_EXCL_START
-bool _remove_elements_from_bin(GstBin *bin, GList *element_list)
-{
- GstElement *element;
- GList *list;
- int count = 0;
-
- RET_VAL_IF(bin == NULL, false, "bin is NULL");
- RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
-
- for (list = element_list; list; list = g_list_next(list)) {
- element = (GstElement *)list->data;
- RET_VAL_IF(!gst_bin_remove(bin, element), false,
- "failed to gst_bin_remove(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
- count++;
- }
-
- LOG_DEBUG("%d elements are removed from bin[%s]", count, GST_ELEMENT_NAME(bin));
-
- return true;
-}
-//LCOV_EXCL_STOP
-
bool _is_encoded_format_supported(webrtc_media_source_type_e type, webrtc_ini_s *ini)
{
const ini_item_media_source_s *ini_source;