#define ELEMENT_NAME_VIDEO_SWITCH "videoSwitch"
#define ELEMENT_NAME_VIDEO_MUTE_SRC "videoMuteSrc"
#define ELEMENT_NAME_VOLUME "volume"
+#define ELEMENT_NAME_AUDIO_SRC "audioSrc"
#define ELEMENT_NAME_MIC_SRC "micSrc"
#define ELEMENT_NAME_FILE_SRC "fileSrc"
#define ELEMENT_NAME_AUDIO_QUEUE "audioQueue"
};
static int __link_source_with_webrtcbin(webrtc_gst_slot_s *source, GstElement *webrtcbin);
+static GstPadProbeReturn __camerasrc_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
static const char * __get_audio_media_type(const char *codec_name)
{
PRINT_CAPS(sink_caps, "capsfilter");
g_object_set(G_OBJECT(capsfilter), "caps", sink_caps, NULL);
source->av[idx].render.appsrc_caps = sink_caps;
+ if (source->av[idx].render.appsrc)
+ g_object_set(G_OBJECT(source->av[idx].render.appsrc), "caps", sink_caps, NULL);
}
source->av[idx].render.need_decoding = true;
PRINT_CAPS(sink_caps, "capsfilter");
g_object_set(G_OBJECT(capsfilter), "caps", sink_caps, NULL);
source->av[idx].render.appsrc_caps = sink_caps;
+ if (source->av[idx].render.appsrc)
+ g_object_set(G_OBJECT(source->av[idx].render.appsrc), "caps", sink_caps, NULL);
}
__add_probe_to_pad_for_render(source, idx, gst_element_get_static_pad(capsfilter, "src"), __source_data_probe_cb);
static int __build_screensrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
{
int ret;
- GstElement *screensrc;
- GstElement *videoconvert;
- GstElement *videotestsrc;
- GstElement *videoswitch;
- GstElement *capsfilter;
GList *switch_src_list = NULL;
- GList *element_list = NULL;
- GstPad *src_pad;
+ GstElement *screensrc = NULL;
+ GstElement *videotestsrc = NULL;
+ GstElement *videoswitch = NULL;
const ini_item_media_source_s *ini_source;
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(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- ret = _add_no_target_ghostpad_to_slot(source, true, &src_pad);
+ if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
+ LOG_ERROR("ini_source is NULL");
+ goto exit;
+ }
+
+ ret = _add_no_target_ghostpad_to_slot(source, true, &source->av[AV_IDX_VIDEO].src_pad);
RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to _add_no_target_ghostpad_to_slot()");
source->media_types = MEDIA_TYPE_VIDEO;
return WEBRTC_ERROR_INVALID_OPERATION;
APPEND_ELEMENT(switch_src_list, screensrc);
- if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
- LOG_ERROR("ini_source is NULL");
- goto exit;
- }
_gst_set_element_properties(screensrc, ini_source->source_element_properties);
if (!(videotestsrc = _create_element(DEFAULT_ELEMENT_VIDEOTESTSRC, ELEMENT_NAME_VIDEO_MUTE_SRC)))
"pattern", 2, /* black */
NULL);
- if (!(videoswitch = _create_element(DEFAULT_ELEMENT_INPUT_SELECTOR, ELEMENT_NAME_VIDEO_SWITCH)))
- goto exit;
- APPEND_ELEMENT(element_list, videoswitch);
-
- if (!source->zerocopy_enabled) {
- if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL)))
- goto exit;
- APPEND_ELEMENT(element_list, videoconvert);
- }
-
- if (__create_rest_of_elements(webrtc, source, true, &element_list, false) != WEBRTC_ERROR_NONE)
- goto exit;
-
if (!__add_elements_to_bin(source->bin, switch_src_list)) {
SAFE_G_LIST_FREE(switch_src_list);
return WEBRTC_ERROR_INVALID_OPERATION;
}
- if (!__add_elements_to_bin(source->bin, element_list)) {
- __remove_elements_from_bin(source->bin, switch_src_list);
- SAFE_G_LIST_FREE(switch_src_list);
- SAFE_G_LIST_FREE(element_list);
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
-
- if (!__link_switch_srcs(videoswitch, switch_src_list))
+ if (!(videoswitch = _create_element(DEFAULT_ELEMENT_INPUT_SELECTOR, ELEMENT_NAME_VIDEO_SWITCH)))
goto exit_with_remove_from_bin;
- if (source->av[AV_IDX_VIDEO].mute) {
- GstPad *pad = gst_element_get_static_pad(videoswitch, "sink_1");
- if (!pad)
- goto exit_with_remove_from_bin;
- g_object_set(G_OBJECT(videoswitch), "active-pad", pad, NULL);
- gst_object_unref(pad);
- }
-
- if (!__link_elements(element_list))
+ if (!gst_bin_add(source->bin, videoswitch)) {
+ LOG_ERROR("failed to gst_bin_add(), bin[%s], videoswitch[%s]", GST_ELEMENT_NAME(source->bin), GST_ELEMENT_NAME(videoswitch));
+ SAFE_GST_OBJECT_UNREF(videoswitch);
goto exit_with_remove_from_bin;
+ }
- if (!(capsfilter = gst_bin_get_by_name(source->bin, ELEMENT_NAME_RTP_CAPSFILTER)))
+ if (!__link_switch_srcs(videoswitch, switch_src_list)) {
+ SAFE_GST_OBJECT_UNREF(videoswitch);
goto exit_with_remove_from_bin;
-
- if (_set_ghost_pad_target(src_pad, capsfilter, true) != WEBRTC_ERROR_NONE)
- goto exit_with_remove_from_bin;
-
- __add_probe_to_pad_for_pause(source, AV_IDX_VIDEO, src_pad, __payloaded_data_probe_cb);
-
- SAFE_G_LIST_FREE(switch_src_list);
- SAFE_G_LIST_FREE(element_list);
+ }
return WEBRTC_ERROR_NONE;
exit_with_remove_from_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 WEBRTC_ERROR_INVALID_OPERATION;
exit:
SAFE_G_LIST_FREE_FULL(switch_src_list, gst_object_unref);
- SAFE_G_LIST_FREE_FULL(element_list, gst_object_unref);
return WEBRTC_ERROR_INVALID_OPERATION;
}
-static int __build_rest_of_videosrc(webrtc_s *webrtc, GstPad *src_pad, GstElement *videosrc_element, webrtc_gst_slot_s *source)
+//LCOV_EXCL_START
+static int __mute_by_changing_property(webrtc_gst_slot_s *source, GstElement *videotestsrc, bool mute)
+{
+ RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+ RET_VAL_IF(videotestsrc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "videotestsrc is NULL");
+
+ if (!g_object_class_find_property(G_OBJECT_GET_CLASS(videotestsrc), "pattern")) {
+ LOG_ERROR("there is no pattern property");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ /* FIXME: get original value from ini file */
+ g_object_set(G_OBJECT(videotestsrc), "pattern", mute ? 2 : 18, NULL); /* 2: black 18: ball */
+
+ return WEBRTC_ERROR_NONE;
+}
+
+static int __mute_by_manipulating_buffer(webrtc_gst_slot_s *source, GstElement *camerasrc, bool mute)
+{
+ g_autoptr(GstPad) src_pad = NULL;
+
+ RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+ RET_VAL_IF(camerasrc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "camerasrc is NULL");
+
+ src_pad = gst_element_get_static_pad(camerasrc, "src");
+ RET_VAL_IF(src_pad == NULL, WEBRTC_ERROR_INVALID_OPERATION, "src_pad is NULL");
+
+ if (mute && source->camerasrc_probe_id == 0) {
+ source->camerasrc_probe_id = gst_pad_add_probe(src_pad, GST_PAD_PROBE_TYPE_BUFFER, __camerasrc_probe_cb, NULL, NULL);
+ if (source->camerasrc_probe_id == 0) {
+ LOG_ERROR("failed to gst_pad_add_probe()");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ } else if (!mute && source->camerasrc_probe_id != 0) {
+ gst_pad_remove_probe(src_pad, source->camerasrc_probe_id);
+ source->camerasrc_probe_id = 0;
+
+ } else {
+ LOG_ERROR("failed to change mute to (%d)", mute);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ return WEBRTC_ERROR_NONE;
+}
+
+static int __mute_by_switching_video(webrtc_gst_slot_s *source, GstElement *videoswitch, bool mute)
+{
+ GstPad *sink_pad = NULL;
+
+ RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+ RET_VAL_IF(videoswitch == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "videoswitch is NULL");
+
+ sink_pad = gst_element_get_static_pad(videoswitch, mute ? "sink_1" : "sink_0");
+ RET_VAL_IF(sink_pad == NULL, WEBRTC_ERROR_INVALID_OPERATION, "sink_pad is NULL");
+
+ g_object_set(G_OBJECT(videoswitch), "active-pad", sink_pad, NULL);
+ gst_object_unref(sink_pad);
+
+ return WEBRTC_ERROR_NONE;
+}
+//LCOV_EXCL_STOP
+
+static int __complete_rest_of_videosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
{
GList *element_list = NULL;
+ GstElement *videosrc;
GstElement *capsfilter;
- const ini_item_media_source_s *ini_source;
+ GstElement *videoswitch = NULL; /* only for screen source */
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
- RET_VAL_IF(src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "src_pad is NULL");
- RET_VAL_IF(videosrc_element == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "videosrc_element is NULL");
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- APPEND_ELEMENT(element_list, videosrc_element);
+ /* skip when it is already completed. e.g) start() -> stop() -> start() again */
+ if (source->av[AV_IDX_VIDEO].render.src_pad_probe_id > 0)
+ return WEBRTC_ERROR_NONE;
- if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
- LOG_ERROR("ini_source is NULL");
- goto exit;
- }
- _gst_set_element_properties(videosrc_element, ini_source->source_element_properties);
+ if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_SCREEN) {
+ GstElement *videoconvert;
- /* NOTE: in case of videotestsrc with mute operation */
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(videosrc_element), "pattern") && source->av[AV_IDX_VIDEO].mute)
- g_object_set(G_OBJECT(videosrc_element), "pattern", 2, NULL); /* 2: black */
+ videoswitch = gst_bin_get_by_name(source->bin, ELEMENT_NAME_VIDEO_SWITCH);
+ RET_VAL_IF(videoswitch == NULL, WEBRTC_ERROR_INVALID_OPERATION, "videoswitch is NULL");
- /* NOTE: in case of an element that supports tizen zerocopy format, not to emit an error in GST_STATE_PLAYING
- * without buffer consumption before finishing negotiation, set this property to 0 here. */
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(videosrc_element)), "empty-buffer-timeout"))
- g_object_set(G_OBJECT(videosrc_element), "empty-buffer-timeout", 0, NULL);
+ if (source->av[AV_IDX_VIDEO].mute &&
+ (__mute_by_switching_video(source, videoswitch, source->av[AV_IDX_VIDEO].mute) != WEBRTC_ERROR_NONE))
+ goto exit;
+
+ if (!source->zerocopy_enabled) {
+ if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL)))
+ goto exit;
+ APPEND_ELEMENT(element_list, videoconvert);
+ }
+ }
if (__create_rest_of_elements(webrtc, source, true, &element_list, false) != WEBRTC_ERROR_NONE)
goto exit;
return WEBRTC_ERROR_INVALID_OPERATION;
}
+ if ((videosrc = gst_bin_get_by_name(source->bin, ELEMENT_NAME_VIDEO_SRC))) {
+
+ if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST) {
+ if (source->av[AV_IDX_VIDEO].mute &&
+ (__mute_by_changing_property(source, videosrc, source->av[AV_IDX_VIDEO].mute) != WEBRTC_ERROR_NONE))
+ goto exit_with_remove_from_bin;
+
+ } else if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_CAMERA) {
+ if (source->av[AV_IDX_VIDEO].mute) {
+ if (!g_strcmp0(GST_ELEMENT_NAME(videosrc), DEFAULT_ELEMENT_VIDEOTESTSRC)) {
+ /* in case of emulator */
+ if (__mute_by_changing_property(source, videosrc, source->av[AV_IDX_VIDEO].mute) != WEBRTC_ERROR_NONE)
+ goto exit_with_remove_from_bin;
+ } else {
+ if (__mute_by_manipulating_buffer(source, videosrc, source->av[AV_IDX_VIDEO].mute) != WEBRTC_ERROR_NONE)
+ goto exit_with_remove_from_bin;
+ }
+ }
+ /* NOTE: in case of an element that supports tizen zerocopy format, not to emit an error in GST_STATE_PLAYING
+ * without buffer consumption before finishing negotiation, set this property to 0 here. */
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(videosrc)), "empty-buffer-timeout"))
+ g_object_set(G_OBJECT(videosrc), "empty-buffer-timeout", 0, NULL);
+ }
+ }
+
+ if (!videoswitch && !videosrc) {
+ LOG_ERROR("both videoswitch and videosrc are NULL");
+ goto exit_with_remove_from_bin;
+ }
+
+ PREPEND_ELEMENT(element_list, videoswitch ? videoswitch : videosrc);
if (!__link_elements(element_list))
goto exit_with_remove_from_bin;
if (!(capsfilter = gst_bin_get_by_name(source->bin, ELEMENT_NAME_RTP_CAPSFILTER)))
goto exit_with_remove_from_bin;
- if (_set_ghost_pad_target(src_pad, capsfilter, true) != WEBRTC_ERROR_NONE)
+ if (_set_ghost_pad_target(source->av[AV_IDX_VIDEO].src_pad, capsfilter, true) != WEBRTC_ERROR_NONE)
+ goto exit_with_remove_from_bin;
+
+ if (__link_source_with_webrtcbin(source, webrtc->gst.webrtcbin) != WEBRTC_ERROR_NONE)
goto exit_with_remove_from_bin;
- __add_probe_to_pad_for_pause(source, AV_IDX_VIDEO, src_pad, __payloaded_data_probe_cb);
+ __add_probe_to_pad_for_pause(source, AV_IDX_VIDEO, source->av[AV_IDX_VIDEO].src_pad, __payloaded_data_probe_cb);
SAFE_G_LIST_FREE(element_list);
{
int ret;
GstElement *camerasrc;
- GstPad *src_pad;
+ const ini_item_media_source_s *ini_source;
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(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- ret = _add_no_target_ghostpad_to_slot(source, true, &src_pad);
+ if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
+ LOG_ERROR("ini_source is NULL");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ ret = _add_no_target_ghostpad_to_slot(source, true, &source->av[AV_IDX_VIDEO].src_pad);
RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to _add_no_target_ghostpad_to_slot()");
source->media_types = MEDIA_TYPE_VIDEO;
if (!(camerasrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_CAMERA), ELEMENT_NAME_VIDEO_SRC)))
return WEBRTC_ERROR_INVALID_OPERATION;
- return __build_rest_of_videosrc(webrtc, src_pad, camerasrc, source);
+ _gst_set_element_properties(camerasrc, ini_source->source_element_properties);
+
+ /* NOTE: in case of an element that supports tizen zerocopy format, not to emit an error in GST_STATE_PLAYING
+ * without buffer consumption before finishing negotiation, set this property to 0 here. */
+ 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 (!gst_bin_add(source->bin, camerasrc)) {
+ LOG_ERROR("failed to gst_bin_add(), bin[%s], camerasrc[%s]", GST_ELEMENT_NAME(source->bin), GST_ELEMENT_NAME(camerasrc));
+ SAFE_GST_OBJECT_UNREF(camerasrc);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ return WEBRTC_ERROR_NONE;
}
-static int __build_rest_of_audiosrc(webrtc_s *webrtc, GstPad *src_pad, GstElement *audiosrc_element, webrtc_gst_slot_s *source)
+static int __complete_rest_of_audiosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
{
GList *element_list = NULL;
+ GstElement *audiosrc;
GstElement *volume;
GstElement *capsfilter;
const ini_item_media_source_s *ini_source;
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
- RET_VAL_IF(src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "src_pad is NULL");
- RET_VAL_IF(audiosrc_element == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "audiosrc_element is NULL");
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- APPEND_ELEMENT(element_list, audiosrc_element);
-
if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
LOG_ERROR("ini_source is NULL");
- goto exit;
+ return WEBRTC_ERROR_INVALID_OPERATION;
}
- _gst_set_element_properties(audiosrc_element, ini_source->source_element_properties);
+
+ /* skip when it is already completed. e.g) start() -> stop() -> start() again */
+ if (source->av[AV_IDX_AUDIO].render.src_pad_probe_id > 0)
+ return WEBRTC_ERROR_NONE;
if (!(volume = _create_element(DEFAULT_ELEMENT_VOLUME, ELEMENT_NAME_VOLUME)))
goto exit;
return WEBRTC_ERROR_INVALID_OPERATION;
}
+ if (!(audiosrc = gst_bin_get_by_name(source->bin, source->type == WEBRTC_MEDIA_SOURCE_TYPE_MIC ?
+ ELEMENT_NAME_MIC_SRC : ELEMENT_NAME_AUDIO_SRC))) {
+ LOG_ERROR("failed to gst_bin_get_by_name()");
+ goto exit_with_remove_from_bin;
+ }
+
+ PREPEND_ELEMENT(element_list, audiosrc);
if (!__link_elements(element_list))
goto exit_with_remove_from_bin;
if (!(capsfilter = gst_bin_get_by_name(source->bin, ELEMENT_NAME_RTP_CAPSFILTER)))
goto exit_with_remove_from_bin;
- if (_set_ghost_pad_target(src_pad, capsfilter, true) != WEBRTC_ERROR_NONE)
+ if (_set_ghost_pad_target(source->av[AV_IDX_AUDIO].src_pad, capsfilter, true) != WEBRTC_ERROR_NONE)
goto exit_with_remove_from_bin;
- __add_probe_to_pad_for_pause(source, AV_IDX_AUDIO, src_pad, __payloaded_data_probe_cb);
+ if (__link_source_with_webrtcbin(source, webrtc->gst.webrtcbin) != WEBRTC_ERROR_NONE)
+ goto exit_with_remove_from_bin;
+
+ __add_probe_to_pad_for_pause(source, AV_IDX_AUDIO, source->av[AV_IDX_AUDIO].src_pad, __payloaded_data_probe_cb);
SAFE_G_LIST_FREE(element_list);
return WEBRTC_ERROR_INVALID_OPERATION;
}
+static void __complete_source_foreach_cb(gpointer key, gpointer value, gpointer user_data)
+{
+ webrtc_gst_slot_s *source = (webrtc_gst_slot_s *)value;
+ webrtc_s *webrtc = (webrtc_s *)user_data;
+
+ if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_FILE ||
+ source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET)
+ return;
+
+ LOG_DEBUG("source[%s, id:%u, type:%d]", (gchar *)key, source->id, source->type);
+
+ if (source->media_types == MEDIA_TYPE_AUDIO)
+ __complete_rest_of_audiosrc(webrtc, source);
+ else
+ __complete_rest_of_videosrc(webrtc, source);
+}
+
+int _complete_sources(webrtc_s *webrtc)
+{
+ RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+
+ g_hash_table_foreach(webrtc->gst.source_slots, __complete_source_foreach_cb, webrtc);
+
+ return WEBRTC_ERROR_NONE;
+}
+
static int __build_audiosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool use_mic)
{
int ret;
const char *source_factory_name;
- GstPad *src_pad;
GstElement *audiosrc;
+ const ini_item_media_source_s *ini_source;
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(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- ret = _add_no_target_ghostpad_to_slot(source, true, &src_pad);
+ if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
+ LOG_ERROR("ini_source is NULL");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ ret = _add_no_target_ghostpad_to_slot(source, true, &source->av[AV_IDX_AUDIO].src_pad);
RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to _add_no_target_ghostpad_to_slot()");
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, use_mic ? WEBRTC_MEDIA_SOURCE_TYPE_MIC : WEBRTC_MEDIA_SOURCE_TYPE_AUDIOTEST);
- if (!(audiosrc = _create_element(source_factory_name, use_mic ? ELEMENT_NAME_MIC_SRC : NULL)))
+ if (!(audiosrc = _create_element(source_factory_name, use_mic ? ELEMENT_NAME_MIC_SRC : ELEMENT_NAME_AUDIO_SRC)))
return WEBRTC_ERROR_INVALID_OPERATION;
- return __build_rest_of_audiosrc(webrtc, src_pad, audiosrc, source);
+ _gst_set_element_properties(audiosrc, ini_source->source_element_properties);
+
+ if (!gst_bin_add(source->bin, audiosrc)) {
+ LOG_ERROR("failed to gst_bin_add(), bin[%s], audiosrc[%s]", GST_ELEMENT_NAME(source->bin), GST_ELEMENT_NAME(audiosrc));
+ SAFE_GST_OBJECT_UNREF(audiosrc);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ return WEBRTC_ERROR_NONE;
}
static int __build_videotestsrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
{
int ret;
GstElement *videotestsrc;
- GstPad *src_pad;
+ const ini_item_media_source_s *ini_source;
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(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- ret = _add_no_target_ghostpad_to_slot(source, true, &src_pad);
+ if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
+ LOG_ERROR("ini_source is NULL");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ ret = _add_no_target_ghostpad_to_slot(source, true, &source->av[AV_IDX_VIDEO].src_pad);
RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to _add_no_target_ghostpad_to_slot()");
source->media_types = MEDIA_TYPE_VIDEO;
if (!(videotestsrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST), ELEMENT_NAME_VIDEO_SRC)))
return WEBRTC_ERROR_INVALID_OPERATION;
- return __build_rest_of_videosrc(webrtc, src_pad, videotestsrc, source);
+ _gst_set_element_properties(videotestsrc, ini_source->source_element_properties);
+
+ if (!gst_bin_add(source->bin, videotestsrc)) {
+ LOG_ERROR("failed to gst_bin_add(), bin[%s], videotestsrc[%s]", GST_ELEMENT_NAME(source->bin), GST_ELEMENT_NAME(videotestsrc));
+ SAFE_GST_OBJECT_UNREF(videotestsrc);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ return WEBRTC_ERROR_NONE;
}
//LCOV_EXCL_START
{
int ret;
GstElement *custom_videosrc;
- GstPad *src_pad;
+ const ini_item_media_source_s *ini_source;
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(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- ret = _add_no_target_ghostpad_to_slot(source, true, &src_pad);
+ if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
+ LOG_ERROR("ini_source is NULL");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ ret = _add_no_target_ghostpad_to_slot(source, true, &source->av[AV_IDX_VIDEO].src_pad);
RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to _add_no_target_ghostpad_to_slot()");
source->media_types = MEDIA_TYPE_VIDEO;
if (!(custom_videosrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_CUSTOM_VIDEO), ELEMENT_NAME_VIDEO_SRC)))
return WEBRTC_ERROR_INVALID_OPERATION;
- return __build_rest_of_videosrc(webrtc, src_pad, custom_videosrc, source);
+ _gst_set_element_properties(custom_videosrc, ini_source->source_element_properties);
+
+ if (!gst_bin_add(source->bin, custom_videosrc)) {
+ LOG_ERROR("failed to gst_bin_add(), bin[%s], custom_videosrc[%s]", GST_ELEMENT_NAME(source->bin), GST_ELEMENT_NAME(custom_videosrc));
+ SAFE_GST_OBJECT_UNREF(custom_videosrc);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ return WEBRTC_ERROR_NONE;
}
static int __build_custom_audiosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
int ret;
const char *source_factory_name;
GstElement *custom_audiosrc;
- GstPad *src_pad;
+ const ini_item_media_source_s *ini_source;
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(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
- ret = _add_no_target_ghostpad_to_slot(source, true, &src_pad);
+ if (!(ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
+ LOG_ERROR("ini_source is NULL");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ ret = _add_no_target_ghostpad_to_slot(source, true, &source->av[AV_IDX_AUDIO].src_pad);
RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to _add_no_target_ghostpad_to_slot()");
source->media_types = MEDIA_TYPE_AUDIO;
if (!(custom_audiosrc = _create_element(source_factory_name, NULL)))
return WEBRTC_ERROR_INVALID_OPERATION;
- return __build_rest_of_audiosrc(webrtc, src_pad, custom_audiosrc, source);
+ _gst_set_element_properties(custom_audiosrc, ini_source->source_element_properties);
+
+ if (!gst_bin_add(source->bin, custom_audiosrc)) {
+ LOG_ERROR("failed to gst_bin_add(), bin[%s], custom_audiosrc[%s]", GST_ELEMENT_NAME(source->bin), GST_ELEMENT_NAME(custom_audiosrc));
+ SAFE_GST_OBJECT_UNREF(custom_audiosrc);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ return WEBRTC_ERROR_NONE;
}
static int __build_filesrc_bin(webrtc_gst_slot_s *source, media_type_e media_type)
return WEBRTC_ERROR_INVALID_OPERATION;
}
- if (type != WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET && type != WEBRTC_MEDIA_SOURCE_TYPE_FILE &&
- __link_source_with_webrtcbin(source, webrtc->gst.webrtcbin) != WEBRTC_ERROR_NONE) {
- LOG_ERROR("failed to __link_source_with_webrtcbin()");
- goto error_after_insert;
- }
-
*source_id = source->id;
LOG_INFO("webrtc[%p] source[%p, name:%s, id:%u]", webrtc, source, bin_name, *source_id);
return WEBRTC_ERROR_NONE;
-error_after_insert:
- g_hash_table_remove(webrtc->gst.source_slots, bin_name);
-
- return WEBRTC_ERROR_INVALID_OPERATION;
-
error:
g_free(bin_name);
g_free(source);
static int __mute_camerasrc(webrtc_gst_slot_s *source, bool mute)
{
- GstElement *camerasrc = NULL;
- g_autoptr(GstPad) src_pad = NULL;
+ int ret;
+ GstElement *camerasrc;
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+ RET_VAL_IF(source->type != WEBRTC_MEDIA_SOURCE_TYPE_CAMERA, WEBRTC_ERROR_INVALID_PARAMETER, "invalid source type");
RET_VAL_IF(source->av[AV_IDX_VIDEO].mute == mute, WEBRTC_ERROR_NONE, "Already %s", mute ? "muted" : "unmuted");
- if ((camerasrc = gst_bin_get_by_name(source->bin, ELEMENT_NAME_VIDEO_SRC))) {
- src_pad = gst_element_get_static_pad(camerasrc, "src");
-
- if (mute && source->camerasrc_probe_id == 0) {
- source->camerasrc_probe_id = gst_pad_add_probe(src_pad, GST_PAD_PROBE_TYPE_BUFFER, __camerasrc_probe_cb, NULL, NULL);
- if (source->camerasrc_probe_id == 0) {
- LOG_ERROR("failed to gst_pad_add_probe()");
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
+ camerasrc = gst_bin_get_by_name(source->bin, ELEMENT_NAME_VIDEO_SRC);
+ RET_VAL_IF(camerasrc == NULL, WEBRTC_ERROR_INVALID_OPERATION, "camerasrc is NULL");
- } else if (!mute && source->camerasrc_probe_id != 0) {
- gst_pad_remove_probe(src_pad, source->camerasrc_probe_id);
- source->camerasrc_probe_id = 0;
-
- } else {
- LOG_ERROR("failed to change mute to (%d)", mute);
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
+ if (!g_strcmp0(GST_ELEMENT_NAME(camerasrc), DEFAULT_ELEMENT_VIDEOTESTSRC)) {
+ /* in case of emulator */
+ if ((ret = __mute_by_changing_property(source, camerasrc, mute)) != WEBRTC_ERROR_NONE)
+ return ret;
+ } else {
+ if ((ret = __mute_by_manipulating_buffer(source, camerasrc, mute)) != WEBRTC_ERROR_NONE)
+ return ret;
}
source->av[AV_IDX_VIDEO].mute = mute;
return WEBRTC_ERROR_NONE;
}
-static int __mute_videosrc(webrtc_gst_slot_s *source, bool mute)
+static int __mute_screensrc(webrtc_gst_slot_s *source, bool mute)
{
- GstElement *video_switch = NULL;
- GstPad *new_pad = NULL;
+ int ret;
+ GstElement *videoswitch;
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+ RET_VAL_IF(source->type != WEBRTC_MEDIA_SOURCE_TYPE_SCREEN, WEBRTC_ERROR_INVALID_PARAMETER, "invalid source type");
RET_VAL_IF(source->av[AV_IDX_VIDEO].mute == mute, WEBRTC_ERROR_NONE, "Already %s", mute ? "muted" : "unmuted");
- if ((video_switch = gst_bin_get_by_name(source->bin, ELEMENT_NAME_VIDEO_SWITCH))) {
- new_pad = gst_element_get_static_pad(video_switch, mute ? "sink_1" : "sink_0");
- RET_VAL_IF(new_pad == NULL, WEBRTC_ERROR_INVALID_OPERATION, "new_pad is NULL");
-
- g_object_set(G_OBJECT(video_switch), "active-pad", new_pad, NULL);
- gst_object_unref(new_pad);
+ if ((videoswitch = gst_bin_get_by_name(source->bin, ELEMENT_NAME_VIDEO_SWITCH))) {
+ if ((ret = __mute_by_switching_video(source, videoswitch, mute)) != WEBRTC_ERROR_NONE)
+ return ret;
}
source->av[AV_IDX_VIDEO].mute = mute;
static int __mute_videotestsrc(webrtc_gst_slot_s *source, bool mute)
{
- GstElement *src_element = NULL;
+ int ret;
+ GstElement *videotestsrc;
RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+ RET_VAL_IF(source->type != WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST, WEBRTC_ERROR_INVALID_PARAMETER, "invalid source type");
RET_VAL_IF(source->av[AV_IDX_VIDEO].mute == mute, WEBRTC_ERROR_NONE, "Already %s", mute ? "muted" : "unmuted");
- if ((src_element = gst_bin_get_by_name(source->bin, ELEMENT_NAME_VIDEO_SRC))) {
- if (!g_object_class_find_property(G_OBJECT_GET_CLASS(src_element), "pattern")) {
- LOG_ERROR("there is no pattern property");
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
- /* FIXME: get original value from ini file */
- g_object_set(G_OBJECT(src_element), "pattern", mute ? 2 : 18, NULL); /* 2: black 18: ball */
+ if ((videotestsrc = gst_bin_get_by_name(source->bin, ELEMENT_NAME_VIDEO_SRC))) {
+ if ((ret = __mute_by_changing_property(source, videotestsrc, mute)) != WEBRTC_ERROR_NONE)
+ return ret;
}
source->av[AV_IDX_VIDEO].mute = mute;
static videosrc_mute_func videosrc_mute_funcs[] = {
[WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST] = __mute_videotestsrc,
[WEBRTC_MEDIA_SOURCE_TYPE_CAMERA] = __mute_camerasrc,
- [WEBRTC_MEDIA_SOURCE_TYPE_SCREEN] = __mute_videosrc
+ [WEBRTC_MEDIA_SOURCE_TYPE_SCREEN] = __mute_screensrc
};
int _set_video_mute(webrtc_s *webrtc, unsigned int source_id, bool mute)
g_object_set(G_OBJECT(appsrc),
"is-live", TRUE,
"format", GST_FORMAT_TIME,
- "caps", source->av[idx].render.appsrc_caps,
NULL);
+ if (source->av[idx].render.appsrc_caps)
+ g_object_set(G_OBJECT(appsrc), "caps", source->av[idx].render.appsrc_caps, NULL);
+
if (source->av[idx].render.need_decoding) {
GstElement *decodebin = _create_element("decodebin", NULL);
if (!decodebin) {