#define GST_KLASS_NAME_CONVERTER_AUDIO "Filter/Converter/Audio"
#define GST_KLASS_NAME_CONVERTER_VIDEO "Filter/Converter/Video"
-#define DEFAULT_ELEMENT_CAMERASRC "v4l2src"
-#define DEFAULT_ELEMENT_AUDIOSRC "pulsesrc"
-#define DEFAULT_ELEMENT_VIDEOTESTSRC "videotestsrc"
-#define DEFAULT_ELEMENT_AUDIOTESTSRC "audiotestsrc"
-#define DEFAULT_ELEMENT_APPSRC "appsrc"
-#define DEFAULT_ELEMENT_SCREENSRC "waylandsrc"
-#define DEFAULT_ELEMENT_VIDEOCONVERT "videoconvert"
-#define DEFAULT_ELEMENT_CAPSFILTER "capsfilter"
-#define DEFAULT_ELEMENT_QUEUE "queue"
-#define DEFAULT_ELEMENT_VOLUME "volume"
+#define DEFAULT_ELEMENT_CAMERASRC "v4l2src"
+#define DEFAULT_ELEMENT_AUDIOSRC "pulsesrc"
+#define DEFAULT_ELEMENT_VIDEOTESTSRC "videotestsrc"
+#define DEFAULT_ELEMENT_AUDIOTESTSRC "audiotestsrc"
+#define DEFAULT_ELEMENT_APPSRC "appsrc"
+#define DEFAULT_ELEMENT_SCREENSRC "waylandsrc"
+#define DEFAULT_ELEMENT_VIDEOCONVERT "videoconvert"
+#define DEFAULT_ELEMENT_CAPSFILTER "capsfilter"
+#define DEFAULT_ELEMENT_QUEUE "queue"
+#define DEFAULT_ELEMENT_VOLUME "volume"
+#define DEFAULT_ELEMENT_INPUT_SELECTOR "input-selector"
#define ELEMENT_NAME_FIRST_CAPSFILTER "firstCapsfilter"
+#define ELEMENT_NAME_RTP_CAPSFILTER "rtpCapsfilter"
#define ELEMENT_NAME_VIDEO_SRC "videoSrc"
#define ELEMENT_NAME_VIDEO_SWITCH "videoSwitch"
#define ELEMENT_NAME_VIDEO_MUTE_SRC "videoMuteSrc"
#define ELEMENT_NAME_VOLUME "volume"
+#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)
+
typedef enum {
CODEC_TYPE_OPUS,
CODEC_TYPE_VORBIS,
return NULL;
}
-static int __create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source,
- GstElement **capsfilter, GstElement **encoder, GstElement **payloader, GstElement **queue, GstElement **capsfilter2)
+static int __create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool need_capsfilter, GList **element_list)
{
+ GstElement *capsfilter = NULL;
+ GstElement *encoder;
+ GstElement *payloader;
+ GstElement *queue;
+ GstElement *capsfilter2;
GstCaps *sink_caps;
element_info_s elem_info;
const gchar *encoder_klass_name;
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
- RET_VAL_IF(encoder == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "encoder is NULL");
- RET_VAL_IF(payloader == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "payloader is NULL");
- RET_VAL_IF(queue == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "queue is NULL");
- RET_VAL_IF(capsfilter2 == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "capsfilter2 is NULL");
+ RET_VAL_IF(element_list == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "element_list is NULL");
- if (capsfilter) {
- if (!(*capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_FIRST_CAPSFILTER))) {
+ if (need_capsfilter) {
+ if (!(capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_FIRST_CAPSFILTER))) {
LOG_ERROR("failed to create capsfilter");
return WEBRTC_ERROR_INVALID_OPERATION;
}
if ((sink_caps = __make_default_raw_caps(source, &webrtc->ini))) {
PRINT_CAPS(sink_caps, "capsfilter");
-
- g_object_set(G_OBJECT(*capsfilter), "caps", sink_caps, NULL);
+ g_object_set(G_OBJECT(capsfilter), "caps", sink_caps, NULL);
gst_caps_unref(sink_caps);
}
}
}
if (source->zerocopy_enabled)
- *encoder = __get_hw_encoder_element(webrtc, source);
+ encoder = __get_hw_encoder_element(webrtc, source);
else
CREATE_ELEMENT_FROM_REGISTRY(elem_info, encoder_klass_name,
__make_default_raw_caps(source, &webrtc->ini),
__make_default_encoded_caps(source, &webrtc->ini, NULL),
- *encoder);
- if (*encoder == NULL)
+ encoder);
+ if (encoder == NULL)
return WEBRTC_ERROR_INVALID_OPERATION;
- encoder_name = gst_element_get_name(*encoder);
+ encoder_name = gst_element_get_name(encoder);
if (encoder_name && (!g_strcmp0(encoder_name, "vp8enc") || !g_strcmp0(encoder_name, "vp9enc"))) {
- g_object_set(G_OBJECT(*encoder), "threads", webrtc->ini.vpxenc_params.threads,
+ g_object_set(G_OBJECT(encoder), "threads", webrtc->ini.vpxenc_params.threads,
"end-usage", webrtc->ini.vpxenc_params.end_usage,
"cpu-used", webrtc->ini.vpxenc_params.cpu_used,
"target-bitrate", webrtc->ini.vpxenc_params.target_bitrate,
CREATE_ELEMENT_FROM_REGISTRY(elem_info, GST_KLASS_NAME_PAYLOADER_RTP,
__make_default_encoded_caps(source, &webrtc->ini, &media_type),
NULL,
- *payloader);
- if (*payloader == NULL) {
+ payloader);
+ if (payloader == NULL) {
g_free(media_type);
return WEBRTC_ERROR_INVALID_OPERATION;
}
- if (!(*queue = _create_element(DEFAULT_ELEMENT_QUEUE, NULL))) {
+ if (!(queue = _create_element(DEFAULT_ELEMENT_QUEUE, NULL))) {
LOG_ERROR("failed to create queue");
g_free(media_type);
return WEBRTC_ERROR_INVALID_OPERATION;
}
- if (!(*capsfilter2 = _create_element(DEFAULT_ELEMENT_CAPSFILTER, NULL))) {
+ if (!(capsfilter2 = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_RTP_CAPSFILTER))) {
LOG_ERROR("failed to create capsfilter");
g_free(media_type);
return WEBRTC_ERROR_INVALID_OPERATION;
}
if ((sink_caps = __make_rtp_caps(media_type, source->id))) {
- g_object_set(G_OBJECT(*capsfilter2), "caps", sink_caps, NULL);
+ g_object_set(G_OBJECT(capsfilter2), "caps", sink_caps, NULL);
gst_caps_unref(sink_caps);
}
g_free(media_type);
+ APPEND_ELEMENT(*element_list, capsfilter);
+ APPEND_ELEMENT(*element_list, encoder);
+ APPEND_ELEMENT(*element_list, payloader);
+ APPEND_ELEMENT(*element_list, queue);
+ APPEND_ELEMENT(*element_list, capsfilter2);
+
return WEBRTC_ERROR_NONE;
}
source->av[probe_userdata->av_idx].src_pad_probe_id, pad, probe_userdata->av_idx, source);
}
-static GstElement * __link_video_switch(GstBin *bin, GstElement *src)
+static bool __add_elements_to_bin(GstBin *bin, GList *element_list)
{
- GstElement *videotestsrc = NULL;
- GstElement *videoswitch = NULL;
+ GstElement *element;
+ GList *list;
+ int count = 0;
- RET_VAL_IF(bin == NULL, NULL, "bin is NULL");
- RET_VAL_IF(src == NULL, NULL, "src is NULL");
+ RET_VAL_IF(bin == NULL, false, "bin is NULL");
+ RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
- if (!(videotestsrc = _create_element(DEFAULT_ELEMENT_VIDEOTESTSRC, ELEMENT_NAME_VIDEO_MUTE_SRC)))
- return NULL;
+ for (list = element_list; list; list = list->next) {
+ element = (GstElement *)list->data;
+ RET_VAL_IF(!gst_bin_add(bin, element), false,
+ "failed to gst_bin_add(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
+ count++;
+ }
- g_object_set(G_OBJECT(videotestsrc), "is-live", TRUE, "pattern", 2, NULL); /* 2: black */
+ LOG_DEBUG("%d elements are added to bin[%s]", count, GST_ELEMENT_NAME(bin));
- if (!(videoswitch = _create_element("input-selector", ELEMENT_NAME_VIDEO_SWITCH))) {
- SAFE_GST_OBJECT_UNREF(videotestsrc);
- return NULL;
+ return true;
+}
+
+static 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++;
}
- gst_bin_add_many(bin, videotestsrc, videoswitch, NULL);
+ LOG_DEBUG("%d elements are removed from bin[%s]", count, GST_ELEMENT_NAME(bin));
+
+ return true;
+}
+
+static void __unref_elements(GList *element_list)
+{
+ GList *list;
+
+ if (!element_list)
+ return;
+
+ for (list = element_list; list; list = g_list_next(list))
+ SAFE_GST_OBJECT_UNREF(list->data);
+}
+
+static 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_DEBUG("[%s] - [%s]", GST_ELEMENT_NAME(prev), GST_ELEMENT_NAME(curr));
+ count++;
+ }
+
+ LOG_DEBUG("%d elements are linked", count);
+
+ return true;
+}
+
+static bool __link_switch_srcs(GstElement *switch_element, GList *switch_src_list)
+{
+ GstElement *element;
+ GList *list;
+
+ RET_VAL_IF(switch_element == NULL, false, "switch_element is NULL");
+ RET_VAL_IF(switch_src_list == NULL, false, "switch_src_list is NULL");
- gst_element_link(src, videoswitch);
- gst_element_link(videotestsrc, videoswitch);
+ for (list = switch_src_list; list; list = g_list_next(list)) {
+ element = (GstElement *)list->data;
+ RET_VAL_IF(!gst_element_link(element, switch_element), false,
+ "failed to gst_element_link(), [%s] - [%s]", GST_ELEMENT_NAME(element), GST_ELEMENT_NAME(switch_element));
- return videoswitch;
+ LOG_DEBUG("[%s] - [%s]", GST_ELEMENT_NAME(element), GST_ELEMENT_NAME(switch_element));
+ }
+
+ return true;
}
-static void __unlink_video_switch(GstBin *bin)
+static GstElement *__find_element_in_bin(GstBin *bin, const gchar *name)
{
- GstElement *videotestsrc = NULL;
- GstElement *videoswitch = NULL;
+ GValue value = G_VALUE_INIT;
+ GstElement *element;
+ GstIterator *bin_iterator;
- videotestsrc = gst_bin_get_by_name(bin, ELEMENT_NAME_VIDEO_MUTE_SRC);
- videoswitch = gst_bin_get_by_name(bin, ELEMENT_NAME_VIDEO_SWITCH);
+ RET_VAL_IF(bin == NULL, NULL, "bin is NULL");
+ RET_VAL_IF(name == NULL, NULL, "name is NULL");
+ RET_VAL_IF(!(bin_iterator = gst_bin_iterate_sorted(bin)), NULL, "bin_iterator is NULL");
- gst_bin_remove_many(bin, videotestsrc, videoswitch, NULL);
+ while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &value)) {
+ element = GST_ELEMENT(g_value_get_object(&value));
+
+ if (g_strrstr(GST_ELEMENT_NAME(element), name)) {
+ LOG_DEBUG("found element by name [%s]", GST_ELEMENT_NAME(element));
+ gst_iterator_free(bin_iterator);
+ return element;
+ }
+
+ g_value_reset(&value);
+ }
+
+ gst_iterator_free(bin_iterator);
+
+ return NULL;
}
static int __build_screensrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
int ret = WEBRTC_ERROR_NONE;
GstElement *screensrc;
GstElement *videoconvert;
- GstElement *capsfilter = NULL;
- GstElement *videoenc = NULL;
- GstElement *videopay = NULL;
- GstElement *queue = NULL;
- GstElement *capsfilter2 = NULL;
- GstElement *video_switch = NULL;
+ GstElement *videotestsrc;
+ GstElement *videoswitch;
+ GstElement *capsfilter;
+ GList *switch_src_list = NULL;
+ GList *element_list = NULL;
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
if (!(screensrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_SCREEN), ELEMENT_NAME_VIDEO_SRC)))
return WEBRTC_ERROR_INVALID_OPERATION;
+ APPEND_ELEMENT(switch_src_list, screensrc);
+
+ if (!(videotestsrc = _create_element(DEFAULT_ELEMENT_VIDEOTESTSRC, ELEMENT_NAME_VIDEO_MUTE_SRC)))
+ goto exit;
+ APPEND_ELEMENT(switch_src_list, videotestsrc);
+
+ g_object_set(G_OBJECT(videotestsrc), "is-live", TRUE, "pattern", 2, NULL); /* 2: black */
+
+ if (!(videoswitch = _create_element(DEFAULT_ELEMENT_INPUT_SELECTOR, ELEMENT_NAME_VIDEO_SWITCH)))
+ goto exit;
+ APPEND_ELEMENT(element_list, videoswitch);
if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL)))
goto exit;
+ APPEND_ELEMENT(element_list, videoconvert);
- if ((ret = __create_rest_of_elements(webrtc, source, &capsfilter, &videoenc, &videopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list)) != WEBRTC_ERROR_NONE)
goto exit;
- gst_bin_add_many(source->bin, screensrc, videoconvert, capsfilter, videoenc, videopay, queue, capsfilter2, NULL);
+ if (!__add_elements_to_bin(source->bin, switch_src_list))
+ goto exit;
- video_switch = __link_video_switch(source->bin, screensrc);
- if (!video_switch)
+ if (!__add_elements_to_bin(source->bin, element_list)) {
+ ret = WEBRTC_ERROR_INVALID_OPERATION;
goto exit_with_remove_from_bin;
+ }
- if (!gst_element_link_many(video_switch, videoconvert, capsfilter, videoenc, videopay, queue, capsfilter2, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
+ if (!__link_switch_srcs(videoswitch, switch_src_list)) {
+ ret = WEBRTC_ERROR_INVALID_OPERATION;
+ goto exit_with_remove_from_bin;
+ }
+
+ if (!__link_elements(element_list)) {
ret = WEBRTC_ERROR_INVALID_OPERATION;
goto exit_with_remove_from_bin;
}
- ret = _set_ghost_pad_target(source->av[AV_IDX_VIDEO].src_pad, capsfilter2, true);
+ if (!(capsfilter = gst_bin_get_by_name(source->bin, ELEMENT_NAME_RTP_CAPSFILTER))) {
+ ret = WEBRTC_ERROR_INVALID_OPERATION;
+ goto exit_with_remove_from_bin;
+ }
+ ret = _set_ghost_pad_target(source->av[AV_IDX_VIDEO].src_pad, capsfilter, true);
if (ret != WEBRTC_ERROR_NONE)
goto exit_with_remove_from_bin;
__add_probe_to_pad(source->av[AV_IDX_VIDEO].src_pad, MEDIA_TYPE_VIDEO, source);
+ SAFE_G_LIST_FREE(switch_src_list);
+ SAFE_G_LIST_FREE(element_list);
+
return WEBRTC_ERROR_NONE;
exit_with_remove_from_bin:
/* elements will be dereferenced */
- gst_bin_remove_many(source->bin, screensrc, videoconvert, capsfilter, videoenc, videopay, queue, capsfilter2, NULL);
- __unlink_video_switch(source->bin);
+ __remove_elements_from_bin(source->bin, switch_src_list);
+ __remove_elements_from_bin(source->bin, element_list);
+ SAFE_G_LIST_FREE(switch_src_list);
+ SAFE_G_LIST_FREE(element_list);
return ret;
exit:
- SAFE_GST_OBJECT_UNREF(screensrc);
- SAFE_GST_OBJECT_UNREF(videoconvert);
- SAFE_GST_OBJECT_UNREF(capsfilter);
- SAFE_GST_OBJECT_UNREF(videoenc);
- SAFE_GST_OBJECT_UNREF(videopay);
- SAFE_GST_OBJECT_UNREF(queue);
- SAFE_GST_OBJECT_UNREF(capsfilter2);
+ __unref_elements(switch_src_list);
+ __unref_elements(element_list);
+ SAFE_G_LIST_FREE(switch_src_list);
+ SAFE_G_LIST_FREE(element_list);
return ret;
}
{
int ret = WEBRTC_ERROR_NONE;
GstElement *camerasrc;
- GstElement *capsfilter = NULL;
- GstElement *videoenc = NULL;
- GstElement *videopay = NULL;
- GstElement *queue = NULL;
- GstElement *capsfilter2 = NULL;
+ GstElement *capsfilter;
+ GList *element_list = NULL;
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
#endif
if (!(camerasrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_CAMERA), ELEMENT_NAME_VIDEO_SRC)))
return WEBRTC_ERROR_INVALID_OPERATION;
+ APPEND_ELEMENT(element_list, camerasrc);
/* FIXME: set camera default setting from ini */
if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(camerasrc)), "empty-buffer-timeout"))
g_object_set(G_OBJECT(camerasrc), "empty-buffer-timeout", 0, NULL);
- if ((ret = __create_rest_of_elements(webrtc, source, &capsfilter, &videoenc, &videopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list)) != WEBRTC_ERROR_NONE)
goto exit;
- gst_bin_add_many(source->bin, camerasrc, capsfilter, videoenc, videopay, queue, capsfilter2, NULL);
- if (!gst_element_link_many(camerasrc, capsfilter, videoenc, videopay, queue, capsfilter2, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
+ if (!__add_elements_to_bin(source->bin, element_list))
+ goto exit;
+
+ if (!__link_elements(element_list)) {
ret = WEBRTC_ERROR_INVALID_OPERATION;
goto exit_with_remove_from_bin;
}
- ret = _set_ghost_pad_target(source->av[AV_IDX_VIDEO].src_pad, capsfilter2, true);
+ if (!(capsfilter = gst_bin_get_by_name(source->bin, ELEMENT_NAME_RTP_CAPSFILTER))) {
+ ret = WEBRTC_ERROR_INVALID_OPERATION;
+ goto exit_with_remove_from_bin;
+ }
+ ret = _set_ghost_pad_target(source->av[AV_IDX_VIDEO].src_pad, capsfilter, true);
if (ret != WEBRTC_ERROR_NONE)
goto exit_with_remove_from_bin;
__add_probe_to_pad(source->av[AV_IDX_VIDEO].src_pad, MEDIA_TYPE_VIDEO, source);
+ SAFE_G_LIST_FREE(element_list);
+
return WEBRTC_ERROR_NONE;
exit_with_remove_from_bin:
/* elements will be dereferenced */
- gst_bin_remove_many(source->bin, camerasrc, capsfilter, videoenc, videopay, queue, capsfilter2, NULL);
+ __remove_elements_from_bin(source->bin, element_list);
+ SAFE_G_LIST_FREE(element_list);
return ret;
exit:
- SAFE_GST_OBJECT_UNREF(camerasrc);
- SAFE_GST_OBJECT_UNREF(capsfilter);
- SAFE_GST_OBJECT_UNREF(videoenc);
- SAFE_GST_OBJECT_UNREF(videopay);
- SAFE_GST_OBJECT_UNREF(queue);
- SAFE_GST_OBJECT_UNREF(capsfilter2);
+ __unref_elements(element_list);
+ SAFE_G_LIST_FREE(element_list);
return ret;
}
-static int __build_audiosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool is_mic)
+static int __build_audiosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool use_mic)
{
int ret = WEBRTC_ERROR_NONE;
const char *source_factory_name;
GstElement *audiosrc;
- GstElement *volume = NULL;
- GstElement *capsfilter = NULL;
- GstElement *audioenc = NULL;
- GstElement *audiopay = NULL;
- GstElement *queue = NULL;
- GstElement *capsfilter2 = NULL;
+ GstElement *volume;
+ GstElement *capsfilter;
+ GList *element_list = NULL;
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
source->media_types = MEDIA_TYPE_AUDIO;
source->zerocopy_enabled = __is_hw_encoder_used(webrtc, source->type, source->media_types);
- source_factory_name = __get_source_element(webrtc, is_mic ? WEBRTC_MEDIA_SOURCE_TYPE_MIC : WEBRTC_MEDIA_SOURCE_TYPE_AUDIOTEST);
+ source_factory_name = __get_source_element(webrtc, use_mic ? WEBRTC_MEDIA_SOURCE_TYPE_MIC : WEBRTC_MEDIA_SOURCE_TYPE_AUDIOTEST);
if (!(audiosrc = _create_element(source_factory_name, NULL)))
return WEBRTC_ERROR_INVALID_OPERATION;
+ APPEND_ELEMENT(element_list, audiosrc);
- if (!is_mic)
+ if (!use_mic)
g_object_set(G_OBJECT(audiosrc), "is-live", TRUE, NULL);
if (!(volume = _create_element(DEFAULT_ELEMENT_VOLUME, ELEMENT_NAME_VOLUME)))
goto exit;
+ APPEND_ELEMENT(element_list, volume);
- if ((ret = __create_rest_of_elements(webrtc, source, &capsfilter, &audioenc, &audiopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list)) != WEBRTC_ERROR_NONE)
goto exit;
- gst_bin_add_many(source->bin, audiosrc, volume, capsfilter, audioenc, audiopay, queue, capsfilter2, NULL);
- if (!gst_element_link_many(audiosrc, volume, capsfilter, audioenc, audiopay, queue, capsfilter2, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
+ if (!__add_elements_to_bin(source->bin, element_list))
+ goto exit;
+
+ if (!__link_elements(element_list)) {
ret = WEBRTC_ERROR_INVALID_OPERATION;
goto exit_with_remove_from_bin;
}
- ret = _set_ghost_pad_target(source->av[AV_IDX_AUDIO].src_pad, capsfilter2, true);
+ if (!(capsfilter = gst_bin_get_by_name(source->bin, ELEMENT_NAME_RTP_CAPSFILTER))) {
+ ret = WEBRTC_ERROR_INVALID_OPERATION;
+ goto exit_with_remove_from_bin;
+ }
+ ret = _set_ghost_pad_target(source->av[AV_IDX_AUDIO].src_pad, capsfilter, true);
if (ret != WEBRTC_ERROR_NONE)
goto exit_with_remove_from_bin;
__add_probe_to_pad(source->av[AV_IDX_AUDIO].src_pad, MEDIA_TYPE_AUDIO, source);
+ SAFE_G_LIST_FREE(element_list);
+
return WEBRTC_ERROR_NONE;
exit_with_remove_from_bin:
/* elements will be dereferenced */
- gst_bin_remove_many(source->bin, audiosrc, volume, capsfilter, audioenc, audiopay, queue, capsfilter2, NULL);
+ __remove_elements_from_bin(source->bin, element_list);
+ SAFE_G_LIST_FREE(element_list);
return ret;
exit:
- SAFE_GST_OBJECT_UNREF(audiosrc);
- SAFE_GST_OBJECT_UNREF(volume);
- SAFE_GST_OBJECT_UNREF(capsfilter);
- SAFE_GST_OBJECT_UNREF(audioenc);
- SAFE_GST_OBJECT_UNREF(audiopay);
- SAFE_GST_OBJECT_UNREF(queue);
- SAFE_GST_OBJECT_UNREF(capsfilter2);
+ __unref_elements(element_list);
+ SAFE_G_LIST_FREE(element_list);
return ret;
}
{
int ret = WEBRTC_ERROR_NONE;
GstElement *videotestsrc;
- GstElement *capsfilter = NULL;
- GstElement *videoenc = NULL;
- GstElement *videopay = NULL;
- GstElement *queue = NULL;
- GstElement *capsfilter2 = NULL;
+ GstElement *capsfilter;
+ GList *element_list = NULL;
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
if (!(videotestsrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST), ELEMENT_NAME_VIDEO_SRC)))
return WEBRTC_ERROR_INVALID_OPERATION;
+ APPEND_ELEMENT(element_list, videotestsrc);
g_object_set(G_OBJECT(videotestsrc), "is-live", TRUE, "pattern", 18, NULL); /* 18: ball */
- if ((ret = __create_rest_of_elements(webrtc, source, &capsfilter, &videoenc, &videopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list)) != WEBRTC_ERROR_NONE)
goto exit;
- gst_bin_add_many(source->bin, videotestsrc, capsfilter, videoenc, videopay, queue, capsfilter2, NULL);
- if (!gst_element_link_many(videotestsrc, capsfilter, videoenc, videopay, queue, capsfilter2, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
+ if (!__add_elements_to_bin(source->bin, element_list))
+ goto exit;
+
+ if (!__link_elements(element_list)) {
ret = WEBRTC_ERROR_INVALID_OPERATION;
goto exit_with_remove_from_bin;
}
- ret = _set_ghost_pad_target(source->av[AV_IDX_VIDEO].src_pad, capsfilter2, true);
+ if (!(capsfilter = gst_bin_get_by_name(source->bin, ELEMENT_NAME_RTP_CAPSFILTER))) {
+ ret = WEBRTC_ERROR_INVALID_OPERATION;
+ goto exit_with_remove_from_bin;
+ }
+ ret = _set_ghost_pad_target(source->av[AV_IDX_VIDEO].src_pad, capsfilter, true);
if (ret != WEBRTC_ERROR_NONE)
goto exit_with_remove_from_bin;
__add_probe_to_pad(source->av[AV_IDX_VIDEO].src_pad, MEDIA_TYPE_VIDEO, source);
+ SAFE_G_LIST_FREE(element_list);
+
return WEBRTC_ERROR_NONE;
exit_with_remove_from_bin:
/* elements will be dereferenced */
- gst_bin_remove_many(source->bin, videotestsrc, capsfilter, videoenc, videopay, queue, capsfilter2, NULL);
+ __remove_elements_from_bin(source->bin, element_list);
+ SAFE_G_LIST_FREE(element_list);
return ret;
exit:
- SAFE_GST_OBJECT_UNREF(videotestsrc);
- SAFE_GST_OBJECT_UNREF(capsfilter);
- SAFE_GST_OBJECT_UNREF(videoenc);
- SAFE_GST_OBJECT_UNREF(videopay);
- SAFE_GST_OBJECT_UNREF(queue);
- SAFE_GST_OBJECT_UNREF(capsfilter2);
+ __unref_elements(element_list);
+ SAFE_G_LIST_FREE(element_list);
return ret;
}
return WEBRTC_ERROR_NONE;
}
-static GstElement *__find_element_in_bin(GstBin *bin, const gchar *name)
-{
- GValue value = G_VALUE_INIT;
- GstElement *element;
- GstIterator *bin_iterator;
-
- RET_VAL_IF(bin == NULL, NULL, "bin is NULL");
- RET_VAL_IF(name == NULL, NULL, "name is NULL");
-
- bin_iterator = gst_bin_iterate_sorted(bin);
-
- while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &value)) {
- element = GST_ELEMENT(g_value_get_object(&value));
-
- if (g_strrstr(GST_ELEMENT_NAME(element), name)) {
- LOG_DEBUG("found element by name [%s]", GST_ELEMENT_NAME(element));
- gst_iterator_free(bin_iterator);
- return element;
- }
-
- g_value_reset(&value);
- }
-
- gst_iterator_free(bin_iterator);
-
- return NULL;
-}
-
static int __complete_mediapacketsrc_from_raw_format(webrtc_s *webrtc, webrtc_gst_slot_s *source)
{
int ret = WEBRTC_ERROR_NONE;
GstPad **src_pad;
GstElement *appsrc;
- GstElement *encoder;
- GstElement *payloader;
- GstElement *queue;
GstElement *capsfilter;
+ GList *element_list = NULL;
GstCaps *sink_caps;
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
source->zerocopy_enabled = __is_hw_encoder_used(webrtc, source->type, source->media_types);
- if ((ret = __create_rest_of_elements(webrtc, source, NULL, &encoder, &payloader, &queue, &capsfilter)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(webrtc, source, false, &element_list)) != WEBRTC_ERROR_NONE)
return ret;
if (!(sink_caps = __make_raw_caps_from_media_format(source))) {
g_object_set(G_OBJECT(appsrc), "caps", sink_caps, NULL);
gst_caps_unref(sink_caps);
- gst_bin_add_many(source->bin, encoder, payloader, queue, capsfilter, NULL);
- if (!gst_element_link_many(appsrc, encoder, payloader, queue, capsfilter, NULL)) {
- LOG_ERROR("failed to gst_element_link_many()");
- return WEBRTC_ERROR_INVALID_OPERATION;
+ if (!__add_elements_to_bin(source->bin, element_list))
+ goto exit;
+
+ PREPEND_ELEMENT(element_list, appsrc);
+ if (!__link_elements(element_list)) {
+ ret = WEBRTC_ERROR_INVALID_OPERATION;
+ goto exit_with_remove_from_bin;
}
+ if (!(capsfilter = gst_bin_get_by_name(source->bin, ELEMENT_NAME_RTP_CAPSFILTER))) {
+ element_list = g_list_nth(element_list, 1); /* skip removing appsrc from bin */
+ ret = WEBRTC_ERROR_INVALID_OPERATION;
+ goto exit_with_remove_from_bin;
+ }
+
+ SAFE_G_LIST_FREE(element_list);
+
return _set_ghost_pad_target(*src_pad, capsfilter, true);
+
+exit_with_remove_from_bin:
+ /* elements will be dereferenced */
+ __remove_elements_from_bin(source->bin, element_list);
+ SAFE_G_LIST_FREE(element_list);
+ return ret;
+exit:
+ __unref_elements(element_list);
+ SAFE_G_LIST_FREE(element_list);
+ return ret;
}
static GstCaps *__make_encoded_caps_for_appsrc(webrtc_gst_slot_s *source)