static GList *get_capture_sources(OwrMediaType types) { static GList *cached_sources = NULL; OwrLocalMediaSource *source; OwrMediaType media_type; GList *result_list = NULL; GList *elem; if (g_once_init_enter(&cached_sources)) { GList *sources = NULL; /* FIXME: This code makes no sense at all, we shouldn't hardcode * capture sources but check what is available. Not everybody has * /dev/video0 and /dev/video1, and not always are they camera * sources... * Use GstDeviceMonitor here! */ source = _owr_local_media_source_new("Audio capture source", OWR_MEDIA_TYPE_AUDIO, OWR_SOURCE_TYPE_CAPTURE); sources = g_list_append(sources, OWR_MEDIA_SOURCE(source)); source = _owr_local_media_source_new("Video capture source", OWR_MEDIA_TYPE_VIDEO, OWR_SOURCE_TYPE_CAPTURE); _owr_local_media_source_set_capture_device_index(source, PRIMARY_VIDEO_DEVICE_INDEX); sources = g_list_append(sources, OWR_MEDIA_SOURCE(source)); source = _owr_local_media_source_new("Video capture source", OWR_MEDIA_TYPE_VIDEO, OWR_SOURCE_TYPE_CAPTURE); _owr_local_media_source_set_capture_device_index(source, SECONDARY_VIDEO_DEVICE_INDEX); sources = g_list_append(sources, OWR_MEDIA_SOURCE(source)); if (g_getenv("OWR_USE_TEST_SOURCES")) { source = _owr_local_media_source_new("Video test source", OWR_MEDIA_TYPE_VIDEO, OWR_SOURCE_TYPE_TEST); sources = g_list_append(sources, OWR_MEDIA_SOURCE(source)); source = _owr_local_media_source_new("Audio test source", OWR_MEDIA_TYPE_AUDIO, OWR_SOURCE_TYPE_TEST); sources = g_list_append(sources, OWR_MEDIA_SOURCE(source)); } g_once_init_leave(&cached_sources, sources); } for (elem = cached_sources; elem; elem = elem->next) { source = OWR_LOCAL_MEDIA_SOURCE(elem->data); g_object_get(source, "media-type", &media_type, NULL); if (types & media_type) { g_object_ref(source); result_list = g_list_append(result_list, source); } } return result_list; }
static OwrMediaSource * pick_a_source(GList *sources, OwrMediaType type, gboolean manual) { GList *item = sources; OwrMediaSource *source = NULL; OwrSourceType source_type; guint i = 1, sel = 0; gboolean have_one = FALSE; while (item) { gchar *name; OwrMediaType media_type; source = OWR_MEDIA_SOURCE(item->data); g_object_get(source, "name", &name, "media-type", &media_type, "type", &source_type, NULL); if (source_type == OWR_SOURCE_TYPE_CAPTURE && media_type == type) { if (manual) { g_print("%u: %s (%s)\n", i, name, media_type == OWR_MEDIA_TYPE_VIDEO ? "video" : "audio"); have_one = TRUE; } else { g_free(name); return source; } } item = item->next; i++; g_free(name); } if (!have_one) return NULL; scanf("%u", &sel); if (sel < 1 || sel >= i) return NULL; return OWR_MEDIA_SOURCE((g_list_nth(sources, sel - 1))->data); }
OwrLocalMediaSource *_owr_local_media_source_new(gchar *name, OwrMediaType media_type, OwrSourceType source_type) { OwrLocalMediaSource *source; source = g_object_new(OWR_TYPE_LOCAL_MEDIA_SOURCE, "name", name, "media-type", media_type, NULL); _owr_media_source_set_type(OWR_MEDIA_SOURCE(source), source_type); return source; }
static void owr_media_source_finalize(GObject *object) { OwrMediaSource *source = OWR_MEDIA_SOURCE(object); OwrMediaSourcePrivate *priv = source->priv; g_free(priv->name); priv->name = NULL; if (priv->source_bin) { GstElement *source_bin = priv->source_bin; priv->source_bin = NULL; gst_element_set_state(source_bin, GST_STATE_NULL); gst_object_unref(source_bin); } if (priv->source_tee) { gst_object_unref(priv->source_tee); priv->source_tee = NULL; } g_mutex_clear(&source->lock); G_OBJECT_CLASS(owr_media_source_parent_class)->finalize(object); }
OwrSession* new_session() { Debug("new session"); OwrMediaSession *session = owr_media_session_new(TRUE); g_signal_connect(session, "on-new-candidate", G_CALLBACK(got_candidate), NULL); g_signal_connect(session, "on-candidate-gathering-done", G_CALLBACK(candidate_gathering_done_go), NULL); g_signal_connect(session, "notify::dtls-certificate", G_CALLBACK(got_dtls_certificate), NULL); if (local_sources != NULL && local_sources->data != NULL) { Debug("setting local source"); owr_media_session_set_send_source(session, OWR_MEDIA_SOURCE(local_sources->data)); } // TODO make the specs (payload:120, encoding VP8, clock: 9000) mutable. OwrPayload *payload = owr_video_payload_new(OWR_CODEC_TYPE_VP8, 120, 90000, TRUE, TRUE); owr_media_session_set_send_payload(session, payload); // Add session to the transport. owr_transport_agent_add_session(transport_agent, OWR_SESSION(session)); return OWR_SESSION(session); }
OwrMediaSource *_owr_uri_source_new(OwrMediaType media_type, guint stream_id, OwrCodecType codec_type, gpointer uridecodebin_ptr) { GstElement *uridecodebin = GST_ELEMENT(uridecodebin_ptr); OwrURISource *source; OwrURISourcePrivate *priv; GEnumClass *enum_class; GEnumValue *enum_value; gchar *name; GstElement *uri_pipeline; GstElement *identity; GstElement *source_bin, *tee; GstElement *fakesink, *queue; GstPad *srcpad, *sinkpad, *ghostpad; gchar *pad_name, *bin_name; enum_class = G_ENUM_CLASS(g_type_class_ref(OWR_TYPE_MEDIA_TYPE)); enum_value = g_enum_get_value(enum_class, media_type); name = g_strdup_printf("%s stream, id: %u", enum_value ? enum_value->value_nick : "unknown", stream_id); g_type_class_unref(enum_class); source = g_object_new(OWR_TYPE_URI_SOURCE, "name", name, "media-type", media_type, NULL); priv = source->priv; priv->stream_id = stream_id; g_free(name); _owr_media_source_set_codec(OWR_MEDIA_SOURCE(source), codec_type); /* create source tee and everything */ if (media_type == OWR_MEDIA_TYPE_VIDEO) bin_name = g_strdup_printf("video-src-%u-%u", codec_type, stream_id); else if (media_type == OWR_MEDIA_TYPE_AUDIO) bin_name = g_strdup_printf("audio-src-%u-%u", codec_type, stream_id); else g_assert_not_reached(); pad_name = g_strdup_printf("src_%u", stream_id); source_bin = gst_bin_new(bin_name); _owr_media_source_set_source_bin(OWR_MEDIA_SOURCE(source), source_bin); identity = gst_element_factory_make("identity", "identity"); g_object_set(identity, "sync", TRUE, NULL); tee = gst_element_factory_make("tee", "tee"); _owr_media_source_set_source_tee(OWR_MEDIA_SOURCE(source), tee); fakesink = gst_element_factory_make("fakesink", "fakesink"); g_object_set(fakesink, "async", FALSE, NULL); g_object_set(fakesink, "enable-last-sample", FALSE, NULL); queue = gst_element_factory_make("queue", "queue"); g_free(bin_name); uri_pipeline = GST_ELEMENT(gst_element_get_parent(uridecodebin)); gst_bin_add_many(GST_BIN(source_bin), identity, tee, queue, fakesink, NULL); LINK_ELEMENTS(identity, tee); LINK_ELEMENTS(tee, queue); LINK_ELEMENTS(queue, fakesink); sinkpad = gst_element_get_static_pad(identity, "sink"); ghostpad = gst_ghost_pad_new("sink", sinkpad); gst_object_unref(sinkpad); gst_element_add_pad(source_bin, ghostpad); gst_bin_add(GST_BIN(uri_pipeline), source_bin); gst_element_sync_state_with_parent(source_bin); gst_object_unref(uri_pipeline); /* Link the uridecodebin to our tee */ srcpad = gst_element_get_static_pad(uridecodebin, pad_name); g_free(pad_name); if (gst_pad_link(srcpad, ghostpad) != GST_PAD_LINK_OK) GST_ERROR("Failed to link source bin to the outside"); return OWR_MEDIA_SOURCE(source); }