#define DEFAULT_ELEMENT_AUDIOTESTSRC "audiotestsrc"
#define DEFAULT_ELEMENT_CAPSFILTER "capsfilter"
#define DEFAULT_ELEMENT_QUEUE "queue"
+#define DEFAULT_ELEMENT_VIDEOCONVERT "videoconvert"
+#define DEFAULT_ELEMENT_AUDIOCONVERT "audioconvert"
+#define DEFAULT_ELEMENT_AUDIORESAMPLE "audioresample"
+#define DEFAULT_ELEMENT_VIDEOSINK "tizenwlsink"
+#define DEFAULT_ELEMENT_AUDIOSINK "pulsesink"
#define DEFAULT_VIDEO_ENCODED_MEDIA_TYPE "video/x-vp8"
#define DEFAULT_VIDEO_RAW_MEDIA_TYPE "video/x-raw"
RET_IF(data == NULL, "data is NULL");
- LOG_DEBUG("[%s, type:%u, id:%u] is removed", GST_ELEMENT_NAME(source->bin), source->type, source->id);
+ LOG_DEBUG("[%s, id:%u] is removed", GST_ELEMENT_NAME(source->bin), source->id);
/* FIXME: do unlink */
LOG_DEBUG("[IceConnectionState] is changed to [%s]", new_state);
}
+static webrtc_gst_slot_s* __find_sink_slot(webrtc_s *webrtc, const gchar *key)
+{
+ RET_VAL_IF(webrtc == NULL, NULL, "webrtc is NULL");
+ RET_VAL_IF(key == NULL, NULL, "key is NULL");
+
+ return g_hash_table_lookup(webrtc->gst.sink_slots, key);
+}
+
+static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *src_pad)
+{
+ webrtc_gst_slot_s *sink;
+ GstElement *videoconvert;
+ GstElement *videosink;
+
+ RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+ RET_VAL_IF(decodebin == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "decodebin is NULL");
+ RET_VAL_IF(src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "src_pad is NULL");
+
+ sink = __find_sink_slot(webrtc, GST_ELEMENT_NAME(decodebin));
+ 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");
+
+ if (!(videoconvert = __create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL))) {
+ LOG_ERROR("failed to create videoconvert");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ /* FIXME: get factory name from ini */
+ if (!(videosink = __create_element(DEFAULT_ELEMENT_VIDEOSINK, NULL))) {
+ LOG_ERROR("failed to create videosink");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ gst_bin_add_many(GST_BIN(sink->bin), videoconvert, videosink, NULL);
+
+ 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_many(decodebin, videoconvert, videosink, NULL)) {
+ LOG_ERROR("failed to gst_element_link_many()");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ return WEBRTC_ERROR_NONE;
+}
+
+static int __build_audiosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *src_pad)
+{
+ webrtc_gst_slot_s *sink;
+ GstElement *audioconvert;
+ GstElement *audioresample;
+ GstElement *audiosink;
+
+ RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+ RET_VAL_IF(decodebin == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "decodebin is NULL");
+ RET_VAL_IF(src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "src_pad is NULL");
+
+ sink = __find_sink_slot(webrtc, GST_ELEMENT_NAME(decodebin));
+ 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");
+
+ if (!(audioconvert = __create_element(DEFAULT_ELEMENT_AUDIOCONVERT, NULL))) {
+ LOG_ERROR("failed to create audioconvert");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ if (!(audioresample = __create_element(DEFAULT_ELEMENT_AUDIORESAMPLE, NULL))) {
+ LOG_ERROR("failed to create audioresample");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ /* FIXME: get factory name from ini */
+ if (!(audiosink = __create_element(DEFAULT_ELEMENT_AUDIOSINK, NULL))) {
+ LOG_ERROR("failed to create audiosink");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ gst_bin_add_many(GST_BIN(sink->bin), audioconvert, audioresample, audiosink, NULL);
+
+ 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 (!gst_element_link_many(decodebin, audioconvert, audioresample, audiosink, NULL)) {
+ LOG_ERROR("failed to gst_element_link_many()");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ return WEBRTC_ERROR_NONE;
+}
+
+static void __decodebin_pad_added_cb(GstElement *decodebin, GstPad *new_pad, gpointer user_data)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ webrtc_s *webrtc = (webrtc_s *)user_data;
+ const gchar *media_type;
+
+ RET_IF(webrtc == NULL, "webrtc is NULL");
+
+ if (GST_PAD_DIRECTION(new_pad) != GST_PAD_SRC)
+ return;
+
+ media_type = gst_structure_get_name(gst_caps_get_structure(gst_pad_get_current_caps(new_pad), 0));
+ LOG_INFO("[%s], new_pad[%s], media_type[%s]", GST_ELEMENT_NAME(decodebin), GST_PAD_NAME(new_pad), media_type);
+
+ if (g_strrstr(media_type, "video")) {
+ ret = __build_videosink(webrtc, decodebin, new_pad);
+
+ } else if (g_strrstr(media_type, "audio")) {
+ ret = __build_audiosink(webrtc, decodebin, new_pad);
+
+ } else {
+ LOG_ERROR("not supported media type[%s]", media_type);
+ return;
+ }
+
+ if (ret != WEBRTC_ERROR_NONE)
+ LOG_ERROR("failed to build a rendering pipeline");
+}
+
+static int __decodebin_autoplug_select_cb(GstElement *decodebin, GstPad *pad, GstCaps *caps, GstElementFactory *factory, gpointer user_data)
+{
+ /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed */
+ typedef enum {
+ GST_AUTOPLUG_SELECT_TRY,
+ GST_AUTOPLUG_SELECT_EXPOSE,
+ GST_AUTOPLUG_SELECT_SKIP
+ } GstAutoplugSelectResult;
+ gchar *factory_name;
+ const gchar *klass;
+ GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
+ webrtc_s *webrtc = (webrtc_s *)user_data;
+
+ RET_VAL_IF(webrtc == NULL, GST_AUTOPLUG_SELECT_SKIP, "webrtc is NULL, skip it");
+
+ factory_name = GST_OBJECT_NAME(factory);
+ klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
+
+ LOG_INFO("factory [name:%s, klass:%s]", factory_name, klass);
+
+ return result;
+}
+
+static unsigned int __get_id_from_pad_name(const gchar* name)
+{
+ gchar **tokens = NULL;
+ gint64 id;
+
+ RET_VAL_IF(name == NULL, 0, "name is NULL");
+
+ tokens = g_strsplit(name, "_", 2);
+ id = g_ascii_strtoll(tokens[1], NULL, 10);
+
+ g_strfreev(tokens);
+
+ return (unsigned int)id;
+}
+
+static GstPad* __add_no_target_ghostpad(GstElement *bin, const char *pad_name, bool is_src)
+{
+ gchar *bin_name = NULL;
+ GstPad *ghost_pad = NULL;
+
+ RET_VAL_IF(bin == NULL, NULL, "bin is NULL");
+ RET_VAL_IF(pad_name == NULL, NULL, "pad_name is NULL");
+
+ if (!(ghost_pad = gst_ghost_pad_new_no_target(pad_name, is_src ? GST_PAD_SRC : GST_PAD_SINK))) {
+ LOG_ERROR("failed to gst_ghost_pad_new_no_target()");
+ return NULL;
+ }
+
+ bin_name = gst_element_get_name(bin);
+ if (gst_element_add_pad(GST_ELEMENT(bin), ghost_pad)) {
+ gst_pad_set_active(ghost_pad, TRUE);
+ LOG_DEBUG("added [%s] empty ghostpad into [%s]", pad_name, bin_name);
+ } else {
+ LOG_ERROR("failed to add empty [%s] ghostpad into [%s]", pad_name, bin_name);
+ g_object_unref(ghost_pad);
+ ghost_pad = NULL;
+ }
+
+ g_free(bin_name);
+
+ return ghost_pad;
+}
+
+static int __add_no_target_ghostpad_to_slot(webrtc_gst_slot_s *slot, gboolean is_src, GstPad **new_pad)
+{
+ gchar *pad_name;
+
+ RET_VAL_IF(slot == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "slot is NULL");
+ RET_VAL_IF(slot->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
+ RET_VAL_IF(new_pad == NULL, WEBRTC_ERROR_INVALID_OPERATION, "new_pad is NULL");
+
+ pad_name = g_strdup_printf("%s_%u", is_src ? "src" : "sink", slot->id);
+ if (!(*new_pad =__add_no_target_ghostpad(slot->bin, pad_name, is_src))) {
+ LOG_ERROR("failed to add new ghost pad[%s] for bin[%s]", pad_name, GST_ELEMENT_NAME(slot->bin));
+ g_free(pad_name);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+ g_free(pad_name);
+
+ return WEBRTC_ERROR_NONE;
+}
+
+static int __set_ghost_pad_target(GstPad *ghost_pad, GstElement *target_element, gboolean is_src)
+{
+ GstPad *target_pad;
+
+ RET_VAL_IF(ghost_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "ghost_pad is NULL");
+ RET_VAL_IF(target_element == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "target_element is NULL");
+
+ if (!(target_pad = gst_element_get_static_pad(target_element, is_src ? "src" : "sink"))) {
+ LOG_ERROR("failed to gst_element_get_static_pad() of [%s]", GST_ELEMENT_NAME(target_element));
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ if (!gst_ghost_pad_set_target(GST_GHOST_PAD(ghost_pad), target_pad)) {
+ LOG_ERROR("failed to gst_ghost_pad_set_target(), ghostpad[%s] -> targetpad[%s]", GST_PAD_NAME(ghost_pad), GST_PAD_NAME(target_pad));
+ gst_object_unref(target_pad);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ gst_object_unref(target_pad);
+
+ LOG_DEBUG("ghostpad[%s] -> target[%s:%s]", GST_PAD_NAME(ghost_pad), GST_ELEMENT_NAME(target_element), GST_PAD_NAME(target_pad));
+
+ return WEBRTC_ERROR_NONE;
+}
+
+static int __add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ unsigned int id;
+ gchar *bin_name;
+ gchar *decodebin_name;
+ webrtc_gst_slot_s *sink;
+ GstElement *decodebin;
+ GstPad *sink_pad;
+
+ 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");
+
+ /* decodebin_name/sink will be freed by function which is set to g_hash_table_new_full() */
+ id = __get_id_from_pad_name(GST_PAD_NAME(src_pad));
+ bin_name = g_strdup_printf("rendering_sink_%u", id);
+ decodebin_name = g_strdup_printf("%s_decodebin", bin_name);
+
+ sink = g_new0(webrtc_gst_slot_s, 1);
+ sink->id = id;
+ sink->bin = gst_bin_new(bin_name);
+ g_free(bin_name);
+
+ decodebin = __create_element("decodebin", decodebin_name);
+ if (!decodebin)
+ goto error_before_insert;
+
+ gst_bin_add(GST_BIN(sink->bin), decodebin);
+
+ g_signal_connect(decodebin, "pad-added", G_CALLBACK(__decodebin_pad_added_cb), webrtc);
+ g_signal_connect(decodebin, "autoplug-select", G_CALLBACK(__decodebin_autoplug_select_cb), webrtc);
+
+ ret = __add_no_target_ghostpad_to_slot(sink, FALSE, &sink_pad);
+ if (ret != WEBRTC_ERROR_NONE)
+ goto error_before_insert;
+
+ ret = __set_ghost_pad_target(sink_pad, decodebin, FALSE);
+ if (ret != WEBRTC_ERROR_NONE)
+ goto error_before_insert;
+
+ if (!gst_bin_add(GST_BIN(webrtc->gst.pipeline), sink->bin)) {
+ LOG_ERROR("failed to gst_bin_add(), [%s] -> [%s] pipeline", GST_ELEMENT_NAME(sink->bin), GST_ELEMENT_NAME(webrtc->gst.pipeline));
+ goto error_before_insert;
+ }
+
+ if (gst_pad_link(src_pad, sink_pad) != GST_PAD_LINK_OK) {
+ LOG_ERROR("failed to gst_pad_link(), %s:%s", GST_PAD_NAME(src_pad), GST_PAD_NAME(sink_pad));
+ goto error_before_insert;
+ }
+
+ LOG_DEBUG("link pads successfully, [%s:%s] - [%s:%s]",
+ GST_ELEMENT_NAME(webrtc->gst.webrtcbin), GST_PAD_NAME(src_pad), GST_ELEMENT_NAME(sink->bin), GST_PAD_NAME(sink_pad));
+
+ if (!g_hash_table_insert(webrtc->gst.sink_slots, decodebin_name, (gpointer)sink)) {
+ LOG_ERROR("should not be reached here, bin_name[%s] already exist, sink id[%u] will be removed", decodebin_name, sink->id);
+ g_hash_table_remove(webrtc->gst.sink_slots, decodebin_name);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ gst_element_sync_state_with_parent(sink->bin);
+
+ LOG_INFO("added a sink slot[%p, id:%u]", sink, sink->id);
+
+ return WEBRTC_ERROR_NONE;
+
+error_before_insert:
+ gst_object_unref(sink_pad);
+ g_free(decodebin_name);
+ g_free(sink);
+
+ return WEBRTC_ERROR_INVALID_OPERATION;
+}
+
+static void __webrtcbin_pad_added_cb(GstElement *webrtcbin, GstPad *new_pad, gpointer user_data)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ webrtc_s *webrtc = (webrtc_s *)user_data;
+
+ RET_IF(webrtc == NULL, "webrtc is NULL");
+
+ if (GST_PAD_DIRECTION(new_pad) != GST_PAD_SRC)
+ return;
+
+ LOG_INFO("new pad[%s] is added", GST_PAD_NAME(new_pad));
+
+ ret = __add_rendering_sink_bin(webrtc, new_pad);
+ RET_IF(ret != WEBRTC_ERROR_NONE, "failed to __add_rendering_sink_bin()");
+}
+
+static void __webrtcbin_no_more_pads_cb(GstElement *webrtcbin, gpointer user_data)
+{
+ webrtc_s *webrtc = (webrtc_s *)user_data;
+
+ RET_IF(webrtcbin == NULL, "webrtcbin is NULL");
+ RET_IF(webrtc == NULL, "webrtc is NULL");
+
+ LOG_DEBUG_LEAVE();
+}
+
int _gst_build_pipeline(webrtc_s *webrtc)
{
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
__connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "notify::signaling-state", G_CALLBACK(__webrtcbin_signaling_state_cb), webrtc);
__connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "notify::ice-gathering-state", G_CALLBACK(__webrtcbin_ice_gathering_state_cb), webrtc);
__connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "notify::ice-connection-state", G_CALLBACK(__webrtcbin_ice_connection_state_cb), webrtc);
+ __connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "pad-added", G_CALLBACK(__webrtcbin_pad_added_cb), webrtc);
+ __connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "no-more-pads", G_CALLBACK(__webrtcbin_no_more_pads_cb), webrtc);
if (!gst_bin_add(GST_BIN(webrtc->gst.pipeline), webrtc->gst.webrtcbin)) {
LOG_ERROR("failed to gst_bin_add(), [%s] -> [%s] pipeline", GST_ELEMENT_NAME(webrtc->gst.webrtcbin), GST_ELEMENT_NAME(webrtc->gst.pipeline));
}
webrtc->gst.source_slots = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __value_destroy_cb);
+ webrtc->gst.sink_slots = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __value_destroy_cb);
return WEBRTC_ERROR_NONE;
if (!webrtc)
return;
+ if (webrtc->gst.sink_slots) {
+ g_hash_table_destroy(webrtc->gst.sink_slots);
+ webrtc->gst.sink_slots = NULL;
+ }
if (webrtc->gst.source_slots) {
g_hash_table_destroy(webrtc->gst.source_slots);
webrtc->gst.source_slots = NULL;
return caps;
}
-static int __set_ghost_pad_target(GstPad *ghost_pad, GstElement *target_element, gboolean is_src)
-{
- GstPad *target_pad;
-
- RET_VAL_IF(ghost_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "ghost_pad is NULL");
- RET_VAL_IF(target_element == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "target_element is NULL");
-
- if (!(target_pad = gst_element_get_static_pad(target_element, is_src ? "src" : "sink"))) {
- LOG_ERROR("failed to gst_element_get_static_pad()");
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
-
- if (!gst_ghost_pad_set_target(GST_GHOST_PAD(ghost_pad), target_pad)) {
- LOG_ERROR("failed to gst_ghost_pad_set_target(), ghostpad[%s] -> targetpad[%s]", GST_PAD_NAME(ghost_pad), GST_PAD_NAME(target_pad));
- gst_object_unref(target_pad);
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
-
- gst_object_unref(target_pad);
-
- LOG_DEBUG("ghostpad[%s] -> target[%s:%s]", GST_PAD_NAME(ghost_pad), GST_ELEMENT_NAME(target_element), GST_PAD_NAME(target_pad));
-
- return WEBRTC_ERROR_NONE;
-}
-
-static int __create_rest_of_elements(webrtc_gst_slot_s *source, GstElement **capsfilter, GstElement **encoder, GstElement **payloader, GstElement **queue, GstElement **capsfilter2)
+static int __create_rest_of_elements(webrtc_gst_slot_s *source, webrtc_media_source_type_e type, GstElement **capsfilter, GstElement **encoder, GstElement **payloader, GstElement **queue, GstElement **capsfilter2)
{
GstCaps *sink_caps;
- webrtc_media_source_type_e type;
element_info_s elem_info;
const gchar *encoder_klass_name;
gchar *media_type;
RET_VAL_IF(queue == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "queue is NULL");
RET_VAL_IF(capsfilter2 == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "capsfilter2 is NULL");
- type = source->type;
-
if (!(*capsfilter = __create_element(DEFAULT_ELEMENT_CAPSFILTER, NULL))) {
LOG_ERROR("failed to create capsfilter");
return WEBRTC_ERROR_INVALID_OPERATION;
}
/* FIXME: set camera default setting from ini */
- if ((ret = __create_rest_of_elements(source, &capsfilter, &videoenc, &videopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(source, WEBRTC_MEDIA_SOURCE_TYPE_CAMERA, &capsfilter, &videoenc, &videopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
return ret;
gst_bin_add_many(GST_BIN(source->bin), camerasrc, capsfilter, videoenc, videopay, queue, capsfilter2, NULL);
return WEBRTC_ERROR_INVALID_OPERATION;
}
- if ((ret = __create_rest_of_elements(source, &capsfilter, &audioenc, &audiopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(source, WEBRTC_MEDIA_SOURCE_TYPE_MIC, &capsfilter, &audioenc, &audiopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
return ret;
gst_bin_add_many(GST_BIN(source->bin), audiosrc, capsfilter, audioenc, audiopay, queue, capsfilter2, NULL);
}
g_object_set(G_OBJECT(videotestsrc), "is-live", TRUE, NULL);
- if ((ret = __create_rest_of_elements(source, &capsfilter, &videoenc, &videopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(source, WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST, &capsfilter, &videoenc, &videopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
return ret;
gst_bin_add_many(GST_BIN(source->bin), videotestsrc, capsfilter, videoenc, videopay, queue, capsfilter2, NULL);
}
g_object_set(G_OBJECT(audiotestsrc), "is-live", TRUE, NULL);
- if ((ret = __create_rest_of_elements(source, &capsfilter, &audioenc, &audiopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
+ if ((ret = __create_rest_of_elements(source, WEBRTC_MEDIA_SOURCE_TYPE_AUDIOTEST, &capsfilter, &audioenc, &audiopay, &queue, &capsfilter2)) != WEBRTC_ERROR_NONE)
return ret;
gst_bin_add_many(GST_BIN(source->bin), audiotestsrc, capsfilter, audioenc, audiopay, queue, capsfilter2, NULL);
return __set_ghost_pad_target(ghost_src_pad, capsfilter2, TRUE);
}
-static GstPad* __add_no_target_ghostpad(GstElement *bin, const char *pad_name)
-{
- gchar *bin_name = NULL;
- GstPad *ghost_pad = NULL;
-
- RET_VAL_IF(bin == NULL, NULL, "bin is NULL");
- RET_VAL_IF(pad_name == NULL, NULL, "pad_name is NULL");
-
- if (!(ghost_pad = gst_ghost_pad_new_no_target(pad_name, GST_PAD_SRC))) {
- LOG_ERROR("failed to gst_ghost_pad_new_no_target()");
- return NULL;
- }
-
- bin_name = gst_element_get_name(bin);
- if (gst_element_add_pad(GST_ELEMENT(bin), ghost_pad)) {
- gst_pad_set_active(ghost_pad, TRUE);
- LOG_DEBUG("added [%s] empty ghostpad into [%s]", pad_name, bin_name);
- } else {
- LOG_ERROR("failed to add empty [%s] ghostpad into [%s]", pad_name, bin_name);
- g_object_unref(ghost_pad);
- ghost_pad = NULL;
- }
-
- g_free(bin_name);
-
- return ghost_pad;
-}
-
-static int __build_source_bin(webrtc_gst_slot_s *source)
+static int __build_source_bin(webrtc_gst_slot_s *source, webrtc_media_source_type_e type)
{
- GstPad *src_pad = NULL;
- gchar *pad_name;
+ int ret = WEBRTC_ERROR_NONE;
+ GstPad *src_pad;
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");
- pad_name = g_strdup_printf("src_%u", source->id);
- if (!(src_pad =__add_no_target_ghostpad(source->bin, pad_name))) {
- LOG_ERROR("failed to add new ghost source pad for source bin");
- g_free(pad_name);
- return WEBRTC_ERROR_INVALID_OPERATION;
- }
- g_free(pad_name);
+ ret = __add_no_target_ghostpad_to_slot(source, TRUE, &src_pad);
+ RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to __add_no_target_ghostpad_to_slot()");
- switch (source->type) {
+ switch (type) {
case WEBRTC_MEDIA_SOURCE_TYPE_CAMERA:
return __build_camerasrc(source, src_pad);
return __build_audiotestsrc(source, src_pad);
default:
- LOG_ERROR_IF_REACHED("type(%d)", source->type);
+ LOG_ERROR_IF_REACHED("type(%d)", type);
return WEBRTC_ERROR_INVALID_PARAMETER;
}
bin_name = g_strdup_printf("media_source_%u", id);
source = g_new0(webrtc_gst_slot_s, 1);
-
- source->type = type;
source->id = id;
source->bin = gst_bin_new(bin_name);
- ret = __build_source_bin(source);
+ ret = __build_source_bin(source, type);
if (ret != WEBRTC_ERROR_NONE) {
LOG_ERROR("failed to __build_source_bin()");
goto error_before_insert;
*source_id = id;
- LOG_INFO("type[%d] source_id[%u] source[%p]", type, *source_id, source);
+ LOG_INFO("added a source slot[%p, id:%u]", source, source->id);
g_free(bin_srcpad_name);