static gpointer gst_wl_display_thread_run (gpointer data) { GstWlDisplay *self = data; GstPollFD pollfd = GST_POLL_FD_INIT; pollfd.fd = wl_display_get_fd (self->display); gst_poll_add_fd (self->wl_fd_poll, &pollfd); gst_poll_fd_ctl_read (self->wl_fd_poll, &pollfd, TRUE); /* main loop */ while (1) { while (wl_display_prepare_read_queue (self->display, self->queue) != 0) wl_display_dispatch_queue_pending (self->display, self->queue); wl_display_flush (self->display); if (gst_poll_wait (self->wl_fd_poll, GST_CLOCK_TIME_NONE) < 0) { gboolean normal = (errno == EBUSY); wl_display_cancel_read (self->display); if (normal) break; else goto error; } else { wl_display_read_events (self->display); wl_display_dispatch_queue_pending (self->display, self->queue); } } return NULL; error: GST_ERROR ("Error communicating with the wayland server"); return NULL; }
static FsMsnPollFD * add_pollfd_locked (FsMsnConnection *self, int fd, PollFdCallback callback, gboolean read, gboolean write, gboolean server) { FsMsnPollFD *pollfd = g_slice_new0 (FsMsnPollFD); gst_poll_fd_init (&pollfd->pollfd); pollfd->pollfd.fd = fd; pollfd->server = server; pollfd->want_read = read; pollfd->want_write = write; pollfd->status = FS_MSN_STATUS_AUTH; gst_poll_add_fd (self->poll, &pollfd->pollfd); gst_poll_fd_ctl_read (self->poll, &pollfd->pollfd, read); gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, write); pollfd->callback = callback; GST_DEBUG ("ADD_POLLFD %p (%p) - error %d, close %d, read %d-%d, write %d-%d", self->pollfds, pollfd, gst_poll_fd_has_error (self->poll, &pollfd->pollfd), gst_poll_fd_has_closed (self->poll, &pollfd->pollfd), pollfd->want_read, gst_poll_fd_can_read (self->poll, &pollfd->pollfd), pollfd->want_write, gst_poll_fd_can_write (self->poll, &pollfd->pollfd)); g_ptr_array_add (self->pollfds, pollfd); gst_poll_restart (self->poll); return pollfd; }
static void gst_fd_src_update_fd (GstFdSrc * src, guint64 size) { struct stat stat_results; GST_DEBUG_OBJECT (src, "fdset %p, old_fd %d, new_fd %d", src->fdset, src->fd, src->new_fd); /* we need to always update the fdset since it may not have existed when * gst_fd_src_update_fd () was called earlier */ if (src->fdset != NULL) { GstPollFD fd = GST_POLL_FD_INIT; if (src->fd >= 0) { fd.fd = src->fd; /* this will log a harmless warning, if it was never added */ gst_poll_remove_fd (src->fdset, &fd); } fd.fd = src->new_fd; gst_poll_add_fd (src->fdset, &fd); gst_poll_fd_ctl_read (src->fdset, &fd, TRUE); } if (src->fd != src->new_fd) { GST_INFO_OBJECT (src, "Updating to fd %d", src->new_fd); src->fd = src->new_fd; GST_INFO_OBJECT (src, "Setting size to fd %" G_GUINT64_FORMAT, size); src->size = size; g_free (src->uri); src->uri = g_strdup_printf ("fd://%d", src->fd); if (fstat (src->fd, &stat_results) < 0) goto not_seekable; if (!S_ISREG (stat_results.st_mode)) goto not_seekable; /* Try a seek of 0 bytes offset to check for seekability */ if (lseek (src->fd, 0, SEEK_CUR) < 0) goto not_seekable; GST_INFO_OBJECT (src, "marking fd %d as seekable", src->fd); src->seekable_fd = TRUE; gst_base_src_set_dynamic_size (GST_BASE_SRC (src), TRUE); } return; not_seekable: { GST_INFO_OBJECT (src, "marking fd %d as NOT seekable", src->fd); src->seekable_fd = FALSE; gst_base_src_set_dynamic_size (GST_BASE_SRC (src), FALSE); } }
static gboolean gst_plugin_loader_try_helper (GstPluginLoader * loader, gchar * location) { char *argv[] = { location, (char *) "-l", NULL }; GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s", location); if (!g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD /* | G_SPAWN_STDERR_TO_DEV_NULL */ , NULL, NULL, &loader->child_pid, &loader->fd_w.fd, &loader->fd_r.fd, NULL, NULL)) return FALSE; gst_poll_add_fd (loader->fdset, &loader->fd_w); gst_poll_add_fd (loader->fdset, &loader->fd_r); gst_poll_fd_ctl_read (loader->fdset, &loader->fd_r, TRUE); loader->tx_buf_write = loader->tx_buf_read = 0; put_packet (loader, PACKET_VERSION, 0, NULL, 0); if (!plugin_loader_sync_with_child (loader)) return FALSE; loader->child_running = TRUE; return TRUE; }
static gboolean gst_shm_sink_start (GstBaseSink * bsink) { GstShmSink *self = GST_SHM_SINK (bsink); GError *err = NULL; self->stop = FALSE; if (!self->socket_path) { GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE, ("Could not open socket."), (NULL)); return FALSE; } GST_DEBUG_OBJECT (self, "Creating new socket at %s" " with shared memory of %d bytes", self->socket_path, self->size); self->pipe = sp_writer_create (self->socket_path, self->size, self->perms); if (!self->pipe) { GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE, ("Could not open socket."), (NULL)); return FALSE; } sp_set_data (self->pipe, self); g_free (self->socket_path); self->socket_path = g_strdup (sp_writer_get_path (self->pipe)); GST_DEBUG ("Created socket at %s", self->socket_path); self->poll = gst_poll_new (TRUE); gst_poll_fd_init (&self->serverpollfd); self->serverpollfd.fd = sp_get_fd (self->pipe); gst_poll_add_fd (self->poll, &self->serverpollfd); gst_poll_fd_ctl_read (self->poll, &self->serverpollfd, TRUE); self->pollthread = g_thread_try_new ("gst-shmsink-poll-thread", pollthread_func, self, &err); if (!self->pollthread) goto thread_error; self->allocator = gst_shm_sink_allocator_new (self); return TRUE; thread_error: sp_writer_close (self->pipe, NULL, NULL); self->pipe = NULL; gst_poll_free (self->poll); GST_ELEMENT_ERROR (self, CORE, THREAD, ("Could not start thread"), ("%s", err->message)); g_error_free (err); return FALSE; }
gboolean _gst_plugin_loader_client_run (void) { GstPluginLoader *l; l = plugin_loader_new (NULL); if (l == NULL) return FALSE; /* On entry, the inward pipe is STDIN, and outward is STDOUT. * Dup those somewhere better so that plugins printing things * won't interfere with anything */ #ifndef G_OS_WIN32 { int dup_fd; dup_fd = dup (0); /* STDIN */ if (dup_fd == -1) { GST_ERROR ("Failed to start. Could no dup STDIN, errno %d", errno); return FALSE; } l->fd_r.fd = dup_fd; close (0); dup_fd = dup (1); /* STDOUT */ if (dup_fd == -1) { GST_ERROR ("Failed to start. Could no dup STDOUT, errno %d", errno); return FALSE; } l->fd_w.fd = dup_fd; close (1); /* Dup stderr down to stdout so things that plugins print are visible, * but don't care if it fails */ dup2 (2, 1); } #else /* FIXME: Use DuplicateHandle and friends on win32 */ l->fd_w.fd = 1; /* STDOUT */ l->fd_r.fd = 0; /* STDIN */ #endif gst_poll_add_fd (l->fdset, &l->fd_w); gst_poll_add_fd (l->fdset, &l->fd_r); gst_poll_fd_ctl_read (l->fdset, &l->fd_r, TRUE); l->is_child = TRUE; GST_DEBUG ("Plugin scanner child running. Waiting for instructions"); /* Loop, listening for incoming packets on the fd and writing responses */ while (!l->rx_done && exchange_packets (l)); plugin_loader_free (l); return TRUE; }
static gboolean gst_avdtp_src_start (GstBaseSrc * bsrc) { GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc); /* None of this can go into prepare() since we need to set up the * connection to figure out what format the device is going to send us. */ if (!gst_avdtp_connection_acquire (&avdtpsrc->conn, FALSE)) { GST_ERROR_OBJECT (avdtpsrc, "Failed to acquire connection"); return FALSE; } if (!gst_avdtp_connection_get_properties (&avdtpsrc->conn)) { GST_ERROR_OBJECT (avdtpsrc, "Failed to get transport properties"); goto fail; } if (!gst_avdtp_connection_conf_recv_stream_fd (&avdtpsrc->conn)) { GST_ERROR_OBJECT (avdtpsrc, "Failed to configure stream fd"); goto fail; } GST_DEBUG_OBJECT (avdtpsrc, "Setting block size to link MTU (%d)", avdtpsrc->conn.data.link_mtu); gst_base_src_set_blocksize (GST_BASE_SRC (avdtpsrc), avdtpsrc->conn.data.link_mtu); avdtpsrc->dev_caps = gst_avdtp_connection_get_caps (&avdtpsrc->conn); if (!avdtpsrc->dev_caps) { GST_ERROR_OBJECT (avdtpsrc, "Failed to get device caps"); goto fail; } gst_poll_fd_init (&avdtpsrc->pfd); avdtpsrc->pfd.fd = g_io_channel_unix_get_fd (avdtpsrc->conn.stream); gst_poll_add_fd (avdtpsrc->poll, &avdtpsrc->pfd); gst_poll_fd_ctl_read (avdtpsrc->poll, &avdtpsrc->pfd, TRUE); gst_poll_set_flushing (avdtpsrc->poll, FALSE); g_atomic_int_set (&avdtpsrc->unlocked, FALSE); /* The life time of the connection is shorter than the src object, so we * don't need to worry about memory management */ gst_avdtp_connection_notify_volume (&avdtpsrc->conn, G_OBJECT (avdtpsrc), "transport-volume"); gst_avdtp_src_start_avrcp (avdtpsrc); return TRUE; fail: gst_avdtp_connection_release (&avdtpsrc->conn); return FALSE; }
static gboolean gst_vaapi_window_wayland_sync (GstVaapiWindow * window) { GstVaapiWindowWaylandPrivate *const priv = GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window); struct wl_display *const wl_display = GST_VAAPI_OBJECT_NATIVE_DISPLAY (window); if (priv->sync_failed) return FALSE; if (priv->pollfd.fd < 0) { priv->pollfd.fd = wl_display_get_fd (wl_display); gst_poll_add_fd (priv->poll, &priv->pollfd); gst_poll_fd_ctl_read (priv->poll, &priv->pollfd, TRUE); } while (g_atomic_int_get (&priv->num_frames_pending) > 0) { while (wl_display_prepare_read_queue (wl_display, priv->event_queue) < 0) { if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0) goto error; } if (wl_display_flush (wl_display) < 0) goto error; again: if (gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE) < 0) { int saved_errno = errno; if (saved_errno == EAGAIN || saved_errno == EINTR) goto again; if (saved_errno == EBUSY) { /* closing */ wl_display_cancel_read (wl_display); return FALSE; } goto error; } if (wl_display_read_events (wl_display) < 0) goto error; if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0) goto error; } return TRUE; /* ERRORS */ error: { priv->sync_failed = TRUE; GST_ERROR ("Error on dispatching events: %s", g_strerror (errno)); return FALSE; } }
static gpointer gst_mfx_window_wayland_thread_run (gpointer window) { GstMfxWindowWaylandPrivate *const priv = GST_MFX_WINDOW_WAYLAND_GET_PRIVATE (window); struct wl_display *const wl_display = GST_MFX_DISPLAY_HANDLE (GST_MFX_WINDOW_DISPLAY (window)); if (priv->sync_failed) return NULL; if (priv->pollfd.fd < 0) { priv->pollfd.fd = wl_display_get_fd (wl_display); gst_poll_add_fd (priv->poll, &priv->pollfd); gst_poll_fd_ctl_read (priv->poll, &priv->pollfd, TRUE); } while (1) { while (wl_display_prepare_read_queue (wl_display, priv->event_queue) < 0) { if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0) goto error; } if (wl_display_flush (wl_display) < 0) goto error; again: if (gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE) < 0) { int saved_errno = errno; if (saved_errno == EAGAIN || saved_errno == EINTR) goto again; wl_display_cancel_read (wl_display); if (saved_errno == EBUSY) /* flushing */ return NULL; else goto error; } if (wl_display_read_events (wl_display) < 0) goto error; if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0) goto error; } return NULL; error: priv->sync_failed = TRUE; GST_ERROR ("Error on dispatching events: %s", g_strerror (errno)); return NULL; }
static void gst_fd_src_update_fd (GstFdSrc * src) { struct stat stat_results; /* we need to always update the fdset since it may not have existed when * gst_fd_src_update_fd() was called earlier */ if (src->fdset != NULL) { GstPollFD fd = GST_POLL_FD_INIT; if (src->fd >= 0) { fd.fd = src->fd; gst_poll_remove_fd (src->fdset, &fd); } fd.fd = src->new_fd; gst_poll_add_fd (src->fdset, &fd); gst_poll_fd_ctl_read (src->fdset, &fd, TRUE); } if (src->fd != src->new_fd) { GST_INFO_OBJECT (src, "Updating to fd %d", src->new_fd); src->fd = src->new_fd; g_free (src->uri); src->uri = g_strdup_printf ("fd://%d", src->fd); if (fstat (src->fd, &stat_results) < 0) goto not_seekable; if (!S_ISREG (stat_results.st_mode)) goto not_seekable; /* Try a seek of 0 bytes offset to check for seekability */ if (lseek (src->fd, 0, SEEK_CUR) < 0) goto not_seekable; GST_INFO_OBJECT (src, "marking fd %d as seekable", src->fd); src->seekable_fd = TRUE; } return; not_seekable: { GST_INFO_OBJECT (src, "marking fd %d as NOT seekable", src->fd); src->seekable_fd = FALSE; } }
static gboolean gst_plugin_loader_try_helper (GstPluginLoader * loader, gchar * location) { char *argv[5] = { NULL, }; int c = 0; #if defined (__APPLE__) && defined (USR_BIN_ARCH_SWITCH) if (gst_plugin_loader_use_usr_bin_arch ()) { argv[c++] = (char *) "/usr/bin/arch"; argv[c++] = (char *) USR_BIN_ARCH_SWITCH; } #endif argv[c++] = location; argv[c++] = (char *) "-l"; argv[c++] = NULL; if (c > 3) { GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s with arch %s", location, argv[1]); } else { GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s", location); } if (!g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD /* | G_SPAWN_STDERR_TO_DEV_NULL */ , NULL, NULL, &loader->child_pid, &loader->fd_w.fd, &loader->fd_r.fd, NULL, NULL)) return FALSE; gst_poll_add_fd (loader->fdset, &loader->fd_w); gst_poll_add_fd (loader->fdset, &loader->fd_r); gst_poll_fd_ctl_read (loader->fdset, &loader->fd_r, TRUE); loader->tx_buf_write = loader->tx_buf_read = 0; put_packet (loader, PACKET_VERSION, 0, NULL, 0); if (!plugin_loader_sync_with_child (loader)) return FALSE; loader->child_running = TRUE; return TRUE; }
static gboolean gst_shm_src_start_reading (GstShmSrc * self) { GstShmPipe *gstpipe; if (!self->socket_path) { GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("No path specified for socket."), (NULL)); return FALSE; } gstpipe = g_slice_new0 (GstShmPipe); gstpipe->use_count = 1; gstpipe->src = gst_object_ref (self); GST_DEBUG_OBJECT (self, "Opening socket %s", self->socket_path); GST_OBJECT_LOCK (self); gstpipe->pipe = sp_client_open (self->socket_path); GST_OBJECT_UNLOCK (self); if (!gstpipe->pipe) { GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE, ("Could not open socket %s: %d %s", self->socket_path, errno, strerror (errno)), (NULL)); gst_shm_pipe_dec (gstpipe); return FALSE; } self->pipe = gstpipe; gst_poll_set_flushing (self->poll, FALSE); gst_poll_fd_init (&self->pollfd); self->pollfd.fd = sp_get_fd (self->pipe->pipe); gst_poll_add_fd (self->poll, &self->pollfd); gst_poll_fd_ctl_read (self->poll, &self->pollfd, TRUE); return TRUE; }
static gboolean gst_dvbsrc_start (GstBaseSrc * bsrc) { GstDvbSrc *src = GST_DVBSRC (bsrc); gst_dvbsrc_open_frontend (src, TRUE); if (!gst_dvbsrc_tune (src)) { GST_ERROR_OBJECT (src, "Not able to lock on to the dvb channel"); close (src->fd_frontend); return FALSE; } if (!gst_dvbsrc_frontend_status (src)) { /* unset filters also */ gst_dvbsrc_unset_pes_filters (src); close (src->fd_frontend); return FALSE; } if (!gst_dvbsrc_open_dvr (src)) { GST_ERROR_OBJECT (src, "Not able to open dvr_device"); /* unset filters also */ gst_dvbsrc_unset_pes_filters (src); close (src->fd_frontend); return FALSE; } if (!(src->poll = gst_poll_new (TRUE))) { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL), ("could not create an fdset: %s (%d)", g_strerror (errno), errno)); /* unset filters also */ gst_dvbsrc_unset_pes_filters (src); close (src->fd_frontend); return FALSE; } else { gst_poll_fd_init (&src->poll_fd_dvr); src->poll_fd_dvr.fd = src->fd_dvr; gst_poll_add_fd (src->poll, &src->poll_fd_dvr); gst_poll_fd_ctl_read (src->poll, &src->poll_fd_dvr, TRUE); } return TRUE; }
/* This function gets called by libcurl after the socket() call but before * the connect() call. */ static int gst_curl_base_sink_transfer_socket_cb (void *clientp, curl_socket_t curlfd, curlsocktype socket_type) { GstCurlBaseSink *sink; gboolean ret = TRUE; sink = (GstCurlBaseSink *) clientp; g_assert (sink); if (curlfd < 0) { /* signal an unrecoverable error to the library which will close the socket and return CURLE_COULDNT_CONNECT */ GST_DEBUG_OBJECT (sink, "no curlfd"); return 1; } GST_OBJECT_LOCK (sink); sink->socket_type = socket_type; if (sink->fd.fd != curlfd) { if (sink->fd.fd > 0 && sink->socket_type != CURLSOCKTYPE_ACCEPT) { ret &= gst_poll_remove_fd (sink->fdset, &sink->fd); } sink->fd.fd = curlfd; ret &= gst_poll_add_fd (sink->fdset, &sink->fd); ret &= gst_poll_fd_ctl_write (sink->fdset, &sink->fd, TRUE); ret &= gst_poll_fd_ctl_read (sink->fdset, &sink->fd, TRUE); } GST_DEBUG_OBJECT (sink, "fd: %d", sink->fd.fd); gst_curl_base_sink_setup_dscp_unlocked (sink); GST_OBJECT_UNLOCK (sink); /* success */ return ret ? 0 : 1; }
/* This function gets called by libcurl after the socket() call but before * the connect() call. */ static int gst_curl_base_sink_transfer_socket_cb (void *clientp, curl_socket_t curlfd, curlsocktype G_GNUC_UNUSED purpose) { GstCurlBaseSink *sink; gboolean ret = TRUE; sink = (GstCurlBaseSink *) clientp; g_assert (sink); if (curlfd < 0) { /* signal an unrecoverable error to the library which will close the socket and return CURLE_COULDNT_CONNECT */ return 1; } gst_poll_fd_init (&sink->fd); sink->fd.fd = curlfd; ret = ret && gst_poll_add_fd (sink->fdset, &sink->fd); ret = ret && gst_poll_fd_ctl_write (sink->fdset, &sink->fd, TRUE); ret = ret && gst_poll_fd_ctl_read (sink->fdset, &sink->fd, TRUE); GST_DEBUG ("fd: %d", sink->fd.fd); GST_OBJECT_LOCK (sink); gst_curl_base_sink_setup_dscp_unlocked (sink); GST_OBJECT_UNLOCK (sink); /* success */ if (ret) { return 0; } else { return 1; } }
static gpointer pollthread_func (gpointer data) { GstShmSink *self = GST_SHM_SINK (data); GList *item; GstClockTime timeout = GST_CLOCK_TIME_NONE; int rv = 0; while (!self->stop) { do { rv = gst_poll_wait (self->poll, timeout); } while (rv < 0 && errno == EINTR); if (rv < 0) { GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed waiting on fd activity"), ("gst_poll_wait returned %d, errno: %d", rv, errno)); return NULL; } timeout = GST_CLOCK_TIME_NONE; if (self->stop) return NULL; if (gst_poll_fd_has_closed (self->poll, &self->serverpollfd)) { GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed read from shmsink"), ("Control socket has closed")); return NULL; } if (gst_poll_fd_has_error (self->poll, &self->serverpollfd)) { GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsink"), ("Control socket has error")); return NULL; } if (gst_poll_fd_can_read (self->poll, &self->serverpollfd)) { ShmClient *client; struct GstShmClient *gclient; GST_OBJECT_LOCK (self); client = sp_writer_accept_client (self->pipe); GST_OBJECT_UNLOCK (self); if (!client) { GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsink"), ("Control socket returns wrong data")); return NULL; } gclient = g_slice_new (struct GstShmClient); gclient->client = client; gst_poll_fd_init (&gclient->pollfd); gclient->pollfd.fd = sp_writer_get_client_fd (client); gst_poll_add_fd (self->poll, &gclient->pollfd); gst_poll_fd_ctl_read (self->poll, &gclient->pollfd, TRUE); self->clients = g_list_prepend (self->clients, gclient); g_signal_emit (self, signals[SIGNAL_CLIENT_CONNECTED], 0, gclient->pollfd.fd); /* we need to call gst_poll_wait before calling gst_poll_* status functions on that new descriptor, so restart the loop, so _wait will have been called on all elements of self->poll, whether they have just been added or not. */ timeout = 0; continue; } again: for (item = self->clients; item; item = item->next) { struct GstShmClient *gclient = item->data; if (gst_poll_fd_has_closed (self->poll, &gclient->pollfd)) { GST_WARNING_OBJECT (self, "One client is gone, closing"); goto close_client; } if (gst_poll_fd_has_error (self->poll, &gclient->pollfd)) { GST_WARNING_OBJECT (self, "One client fd has error, closing"); goto close_client; } if (gst_poll_fd_can_read (self->poll, &gclient->pollfd)) { int rv; gpointer tag = NULL; GST_OBJECT_LOCK (self); rv = sp_writer_recv (self->pipe, gclient->client, &tag); GST_OBJECT_UNLOCK (self); if (rv < 0) { GST_WARNING_OBJECT (self, "One client has read error," " closing (retval: %d errno: %d)", rv, errno); goto close_client; } g_assert (rv == 0 || tag == NULL); if (rv == 0) gst_buffer_unref (tag); } continue; close_client: { GSList *list = NULL; GST_OBJECT_LOCK (self); sp_writer_close_client (self->pipe, gclient->client, (sp_buffer_free_callback) free_buffer_locked, (void **) &list); GST_OBJECT_UNLOCK (self); g_slist_free_full (list, (GDestroyNotify) gst_buffer_unref); } gst_poll_remove_fd (self->poll, &gclient->pollfd); self->clients = g_list_remove (self->clients, gclient); g_signal_emit (self, signals[SIGNAL_CLIENT_DISCONNECTED], 0, gclient->pollfd.fd); g_slice_free (struct GstShmClient, gclient); goto again; } g_cond_broadcast (&self->cond); }
static void connection_cb (FsMsnConnection *self, FsMsnPollFD *pollfd) { gboolean success = FALSE; GST_DEBUG ("handler called on fd:%d server: %d status:%d r:%d w:%d", pollfd->pollfd.fd, pollfd->server, pollfd->status, gst_poll_fd_can_read (self->poll, &pollfd->pollfd), gst_poll_fd_can_write (self->poll, &pollfd->pollfd)); if (gst_poll_fd_has_error (self->poll, &pollfd->pollfd) || gst_poll_fd_has_closed (self->poll, &pollfd->pollfd)) { GST_WARNING ("connecton closed or error (error: %d closed: %d)", gst_poll_fd_has_error (self->poll, &pollfd->pollfd), gst_poll_fd_has_closed (self->poll, &pollfd->pollfd)); goto error; } if (gst_poll_fd_can_read (self->poll, &pollfd->pollfd)) { switch (pollfd->status) { case FS_MSN_STATUS_AUTH: if (pollfd->server) { gchar str[35] = {0}; gchar check[35] = {0}; if (recv (pollfd->pollfd.fd, str, 34, 0) == 34) { GST_DEBUG ("Got %s, checking if it's auth", str); FS_MSN_CONNECTION_LOCK(self); snprintf(check, 35, "recipientid=%s&sessionid=%d\r\n\r\n", self->local_recipient_id, self->session_id); FS_MSN_CONNECTION_UNLOCK(self); if (strncmp (str, check, 35) == 0) { GST_DEBUG ("Authentication successful"); pollfd->status = FS_MSN_STATUS_CONNECTED; pollfd->want_write = TRUE; gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, TRUE); } else { GST_WARNING ("Authentication failed check=%s", check); goto error; } } else { gchar error_str[256]; strerror_r (errno, error_str, 256); GST_WARNING ("auth: %s", error_str); goto error; } } else { GST_ERROR ("shouldn't receive data when client on AUTH state"); goto error; } break; case FS_MSN_STATUS_CONNECTED: if (!pollfd->server) { gchar str[14] = {0}; ssize_t size; size = recv (pollfd->pollfd.fd, str, 13, MSG_PEEK); if (size > 0) { GST_DEBUG ("Got %s, checking if it's connected", str); if (size == 13 && strcmp (str, "connected\r\n\r\n") == 0) { GST_DEBUG ("connection successful"); recv (pollfd->pollfd.fd, str, 13, 0); pollfd->status = FS_MSN_STATUS_CONNECTED2; pollfd->want_write = TRUE; gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, TRUE); } else if (!self->producer) { GST_DEBUG ("connection successful"); pollfd->status = FS_MSN_STATUS_SEND_RECEIVE; success = TRUE; } else { GST_WARNING ("connected failed"); goto error; } } else { gchar error_str[256]; strerror_r (errno, error_str, 256); GST_WARNING ("recv: %s", error_str); goto error; } } else { GST_ERROR ("shouldn't receive data when server on CONNECTED state"); goto error; } break; case FS_MSN_STATUS_CONNECTED2: if (pollfd->server) { gchar str[14] = {0}; ssize_t size; size = recv (pollfd->pollfd.fd, str, 13, MSG_PEEK); if (size > 0) { GST_DEBUG ("Got %s, checking if it's connected", str); if (size == 13 && strcmp (str, "connected\r\n\r\n") == 0) { GST_DEBUG ("connection successful"); recv (pollfd->pollfd.fd, str, 13, 0); pollfd->status = FS_MSN_STATUS_SEND_RECEIVE; success = TRUE; } else if (!self->producer) { GST_DEBUG ("connection successful"); pollfd->status = FS_MSN_STATUS_SEND_RECEIVE; success = TRUE; } else { GST_WARNING ("connected failed"); goto error; } } else { gchar error_str[256]; strerror_r (errno, error_str, 256); GST_WARNING ("recv: %s", error_str); goto error; } } else { GST_ERROR ("shouldn't receive data when client on CONNECTED2 state"); goto error; } break; default: GST_ERROR ("Invalid status %d", pollfd->status); goto error; break; } } else if (gst_poll_fd_can_write (self->poll, &pollfd->pollfd)) { pollfd->want_write = FALSE; gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, FALSE); switch (pollfd->status) { case FS_MSN_STATUS_AUTH: if (!pollfd->server) { gchar *str; FS_MSN_CONNECTION_LOCK(self); str = g_strdup_printf("recipientid=%s&sessionid=%d\r\n\r\n", self->remote_recipient_id, self->session_id); FS_MSN_CONNECTION_UNLOCK(self); if (send(pollfd->pollfd.fd, str, strlen (str), 0) != -1) { GST_DEBUG ("Sent %s", str); pollfd->status = FS_MSN_STATUS_CONNECTED; g_free (str); } else { gchar error_str[256]; strerror_r (errno, error_str, 256); GST_WARNING ("auth send: %s", error_str); g_free (str); goto error; } } break; case FS_MSN_STATUS_CONNECTED: if (pollfd->server) { if (send(pollfd->pollfd.fd, "connected\r\n\r\n", 13, 0) != -1) { GST_DEBUG ("sent connected"); if (self->producer) { pollfd->status = FS_MSN_STATUS_SEND_RECEIVE; success = TRUE; } else { pollfd->status = FS_MSN_STATUS_CONNECTED2; } } else { gchar error_str[256]; strerror_r (errno, error_str, 256); GST_WARNING ("sending connected: %s", error_str); goto error; } } else { GST_DEBUG ("shouldn't receive data when server on CONNECTED state"); goto error; } break; case FS_MSN_STATUS_CONNECTED2: if (!pollfd->server) { if (send(pollfd->pollfd.fd, "connected\r\n\r\n", 13, 0) != -1) { GST_DEBUG ("sent connected"); pollfd->status = FS_MSN_STATUS_SEND_RECEIVE; success = TRUE; } else { gchar error_str[256]; strerror_r (errno, error_str, 256); GST_WARNING ("sending connected: %s", error_str); goto error; } } else { GST_ERROR ("shouldn't receive data when client on CONNECTED2 state"); goto error; } break; default: GST_ERROR ("Invalid status %d", pollfd->status); goto error; break; } } if (success) { // success! we need to shutdown/close all other channels shutdown_fd (self, pollfd, FALSE); g_signal_emit (self, signals[SIGNAL_CONNECTED], 0, pollfd->pollfd.fd); pollfd->want_read = FALSE; pollfd->want_write = FALSE; gst_poll_fd_ctl_read (self->poll, &pollfd->pollfd, FALSE); gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, FALSE); } return; error: /* Error */ GST_WARNING ("Got error from fd %d, closing", pollfd->pollfd.fd); shutdown_fd (self, pollfd, TRUE); FS_MSN_CONNECTION_LOCK (self); success = (self->pollfds->len > 1); FS_MSN_CONNECTION_UNLOCK (self); if (!success) g_signal_emit (self, signals[SIGNAL_CONNECTION_FAILED], 0); return; }
static gboolean gst_net_client_clock_start (GstNetClientClock * self) { struct sockaddr_in servaddr, myaddr; socklen_t len; gint ret; GError *error; g_return_val_if_fail (self->address != NULL, FALSE); g_return_val_if_fail (self->servaddr == NULL, FALSE); if ((ret = socket (AF_INET, SOCK_DGRAM, 0)) < 0) goto no_socket; self->priv->sock.fd = ret; len = sizeof (myaddr); ret = getsockname (self->priv->sock.fd, (struct sockaddr *) &myaddr, &len); if (ret < 0) goto getsockname_error; memset (&servaddr, 0, sizeof (servaddr)); servaddr.sin_family = AF_INET; /* host byte order */ servaddr.sin_port = htons (self->port); /* short, network byte order */ GST_DEBUG_OBJECT (self, "socket opened on UDP port %hd", ntohs (servaddr.sin_port)); if (!inet_aton (self->address, &servaddr.sin_addr)) goto bad_address; self->servaddr = g_malloc (sizeof (struct sockaddr_in)); memcpy (self->servaddr, &servaddr, sizeof (servaddr)); GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->address, self->port); gst_poll_add_fd (self->priv->fdset, &self->priv->sock); gst_poll_fd_ctl_read (self->priv->fdset, &self->priv->sock, TRUE); self->thread = g_thread_create (gst_net_client_clock_thread, self, TRUE, &error); if (!self->thread) goto no_thread; return TRUE; /* ERRORS */ no_socket: { GST_ERROR_OBJECT (self, "socket failed %d: %s (%d)", ret, g_strerror (errno), errno); return FALSE; } getsockname_error: { GST_ERROR_OBJECT (self, "getsockname failed %d: %s (%d)", ret, g_strerror (errno), errno); close (self->priv->sock.fd); self->priv->sock.fd = -1; return FALSE; } bad_address: { GST_ERROR_OBJECT (self, "inet_aton failed %d: %s (%d)", ret, g_strerror (errno), errno); close (self->priv->sock.fd); self->priv->sock.fd = -1; return FALSE; } no_thread: { GST_ERROR_OBJECT (self, "could not create thread: %s", error->message); gst_poll_remove_fd (self->priv->fdset, &self->priv->sock); close (self->priv->sock.fd); self->priv->sock.fd = -1; g_free (self->servaddr); self->servaddr = NULL; g_error_free (error); return FALSE; } }
static gboolean handle_rx_packet (GstPluginLoader * l, guint pack_type, guint32 tag, guint8 * payload, guint payload_len) { gboolean res = TRUE; switch (pack_type) { case PACKET_EXIT: gst_poll_fd_ctl_read (l->fdset, &l->fd_r, FALSE); if (l->is_child) { /* Respond */ put_packet (l, PACKET_EXIT, 0, NULL, 0); } l->rx_done = TRUE; return TRUE; case PACKET_LOAD_PLUGIN:{ if (!l->is_child) return TRUE; /* Payload is the filename to load */ res = do_plugin_load (l, (gchar *) payload, tag); break; } case PACKET_PLUGIN_DETAILS:{ gchar *tmp = (gchar *) payload; PendingPluginEntry *entry = NULL; GList *cur; GST_DEBUG_OBJECT (l->registry, "Received plugin details from child w/ tag %u. %d bytes info", tag, payload_len); /* Assume that tagged details come back in the order * we requested, and delete anything before (but not * including) this one */ cur = l->pending_plugins; while (cur) { PendingPluginEntry *e = (PendingPluginEntry *) (cur->data); if (e->tag > tag) break; if (e->tag == tag) { entry = e; break; } else { cur = g_list_delete_link (cur, cur); g_free (e->filename); g_slice_free (PendingPluginEntry, e); } } l->pending_plugins = cur; if (cur == NULL) l->pending_plugins_tail = NULL; if (payload_len > 0) { GstPlugin *newplugin = NULL; if (!_priv_gst_registry_chunks_load_plugin (l->registry, &tmp, tmp + payload_len, &newplugin)) { /* Got garbage from the child, so fail and trigger replay of plugins */ GST_ERROR_OBJECT (l->registry, "Problems loading plugin details with tag %u from scanner", tag); return FALSE; } newplugin->flags &= ~GST_PLUGIN_FLAG_CACHED; GST_LOG_OBJECT (l->registry, "marking plugin %p as registered as %s", newplugin, newplugin->filename); newplugin->registered = TRUE; /* We got a set of plugin details - remember it for later */ l->got_plugin_details = TRUE; } else if (entry != NULL) { /* Create a blacklist entry for this file to prevent scanning every time */ plugin_loader_create_blacklist_plugin (l, entry); l->got_plugin_details = TRUE; } if (entry != NULL) { g_free (entry->filename); g_slice_free (PendingPluginEntry, entry); } /* Remove the plugin entry we just loaded */ cur = l->pending_plugins; if (cur != NULL) cur = g_list_delete_link (cur, cur); l->pending_plugins = cur; if (cur == NULL) l->pending_plugins_tail = NULL; break; } case PACKET_SYNC: if (l->is_child) { /* Respond with our reply - also a sync */ put_packet (l, PACKET_SYNC, tag, NULL, 0); GST_LOG ("Got SYNC in child - replying"); } else l->rx_got_sync = TRUE; break; case PACKET_VERSION: if (l->is_child) { /* Respond with our reply - a version packet, with the version */ const gint version_len = sizeof (guint32) + GST_MAGIC_BINARY_VERSION_LEN; guint8 version_info[sizeof (guint32) + GST_MAGIC_BINARY_VERSION_LEN]; memset (version_info, 0, version_len); GST_WRITE_UINT32_BE (version_info, loader_protocol_version); memcpy (version_info + sizeof (guint32), GST_MAGIC_BINARY_VERSION_STR, strlen (GST_MAGIC_BINARY_VERSION_STR)); put_packet (l, PACKET_VERSION, tag, version_info, version_len); GST_LOG ("Got VERSION in child - replying %u", loader_protocol_version); } else { res = check_protocol_version (l, payload, payload_len); } break; default: return FALSE; /* Invalid packet -> something is wrong */ } return res; }
static gboolean gst_net_time_provider_start (GstNetTimeProvider * self) { gint ru; struct sockaddr_in my_addr; guint len; int port; gint ret; GError *error; if ((ret = socket (AF_INET, SOCK_DGRAM, 0)) < 0) goto no_socket; self->priv->sock.fd = ret; ru = 1; ret = setsockopt (self->priv->sock.fd, SOL_SOCKET, SO_REUSEADDR, &ru, sizeof (ru)); if (ret < 0) goto setsockopt_error; memset (&my_addr, 0, sizeof (my_addr)); my_addr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons ((gint16) self->port); /* short, network byte order */ my_addr.sin_addr.s_addr = INADDR_ANY; if (self->address) inet_aton (self->address, &my_addr.sin_addr); GST_DEBUG_OBJECT (self, "binding on port %d", self->port); ret = bind (self->priv->sock.fd, (struct sockaddr *) &my_addr, sizeof (my_addr)); if (ret < 0) goto bind_error; len = sizeof (my_addr); #ifdef G_OS_WIN32 ret = getsockname (self->priv->sock.fd, (struct sockaddr *) &my_addr, (gint *) & len); #else ret = getsockname (self->priv->sock.fd, (struct sockaddr *) &my_addr, &len); #endif if (ret < 0) goto getsockname_error; port = ntohs (my_addr.sin_port); GST_DEBUG_OBJECT (self, "bound, on port %d", port); if (port != self->port) { self->port = port; GST_DEBUG_OBJECT (self, "notifying %d", port); g_object_notify (G_OBJECT (self), "port"); } gst_poll_add_fd (self->priv->fdset, &self->priv->sock); gst_poll_fd_ctl_read (self->priv->fdset, &self->priv->sock, TRUE); self->thread = g_thread_create (gst_net_time_provider_thread, self, TRUE, &error); if (!self->thread) goto no_thread; return TRUE; /* ERRORS */ no_socket: { GST_ERROR_OBJECT (self, "socket failed %d: %s (%d)", ret, g_strerror (errno), errno); return FALSE; } setsockopt_error: { close (self->priv->sock.fd); self->priv->sock.fd = -1; GST_ERROR_OBJECT (self, "setsockopt failed %d: %s (%d)", ret, g_strerror (errno), errno); return FALSE; } bind_error: { close (self->priv->sock.fd); self->priv->sock.fd = -1; GST_ERROR_OBJECT (self, "bind failed %d: %s (%d)", ret, g_strerror (errno), errno); return FALSE; } getsockname_error: { close (self->priv->sock.fd); self->priv->sock.fd = -1; GST_ERROR_OBJECT (self, "getsockname failed %d: %s (%d)", ret, g_strerror (errno), errno); return FALSE; } no_thread: { gst_poll_remove_fd (self->priv->fdset, &self->priv->sock); close (self->priv->sock.fd); self->priv->sock.fd = -1; GST_ERROR_OBJECT (self, "could not create thread: %s", error->message); g_error_free (error); return FALSE; } }
static gpointer pollthread_func (gpointer data) { GstShmSink *self = GST_SHM_SINK (data); GList *item; while (!self->stop) { if (gst_poll_wait (self->poll, GST_CLOCK_TIME_NONE) < 0) return NULL; if (self->stop) return NULL; if (gst_poll_fd_has_closed (self->poll, &self->serverpollfd)) { GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed read from shmsink"), ("Control socket has closed")); return NULL; } if (gst_poll_fd_has_error (self->poll, &self->serverpollfd)) { GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsink"), ("Control socket has error")); return NULL; } if (gst_poll_fd_can_read (self->poll, &self->serverpollfd)) { ShmClient *client; struct GstShmClient *gclient; GST_OBJECT_LOCK (self); client = sp_writer_accept_client (self->pipe); GST_OBJECT_UNLOCK (self); if (!client) { GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsink"), ("Control socket returns wrong data")); return NULL; } gclient = g_slice_new (struct GstShmClient); gclient->client = client; gst_poll_fd_init (&gclient->pollfd); gclient->pollfd.fd = sp_writer_get_client_fd (client); gst_poll_add_fd (self->poll, &gclient->pollfd); gst_poll_fd_ctl_read (self->poll, &gclient->pollfd, TRUE); self->clients = g_list_prepend (self->clients, gclient); g_signal_emit (self, signals[SIGNAL_CLIENT_CONNECTED], 0, gclient->pollfd.fd); } again: for (item = self->clients; item; item = item->next) { struct GstShmClient *gclient = item->data; if (gst_poll_fd_has_closed (self->poll, &gclient->pollfd)) { GST_WARNING_OBJECT (self, "One client is gone, closing"); goto close_client; } if (gst_poll_fd_has_error (self->poll, &gclient->pollfd)) { GST_WARNING_OBJECT (self, "One client fd has error, closing"); goto close_client; } if (gst_poll_fd_can_read (self->poll, &gclient->pollfd)) { int rv; GST_OBJECT_LOCK (self); rv = sp_writer_recv (self->pipe, gclient->client); GST_OBJECT_UNLOCK (self); if (rv < 0) { GST_WARNING_OBJECT (self, "One client has read error," " closing (retval: %d errno: %d)", rv, errno); goto close_client; } } continue; close_client: GST_OBJECT_LOCK (self); sp_writer_close_client (self->pipe, gclient->client); GST_OBJECT_UNLOCK (self); gst_poll_remove_fd (self->poll, &gclient->pollfd); self->clients = g_list_remove (self->clients, gclient); g_signal_emit (self, signals[SIGNAL_CLIENT_DISCONNECTED], 0, gclient->pollfd.fd); g_slice_free (struct GstShmClient, gclient); goto again; } g_cond_broadcast (self->cond); }
static gboolean gst_kms_sink_start (GstBaseSink * bsink) { GstKMSSink *self; drmModeRes *res; drmModeConnector *conn; drmModeCrtc *crtc; drmModePlaneRes *pres; drmModePlane *plane; gboolean universal_planes; gboolean ret; self = GST_KMS_SINK (bsink); universal_planes = FALSE; ret = FALSE; res = NULL; conn = NULL; crtc = NULL; pres = NULL; plane = NULL; if (self->devname) self->fd = drmOpen (self->devname, NULL); else self->fd = kms_open (&self->devname); if (self->fd < 0) goto open_failed; log_drm_version (self); if (!get_drm_caps (self)) goto bail; res = drmModeGetResources (self->fd); if (!res) goto resources_failed; if (self->conn_id == -1) conn = find_main_monitor (self->fd, res); else conn = drmModeGetConnector (self->fd, self->conn_id); if (!conn) goto connector_failed; crtc = find_crtc_for_connector (self->fd, res, conn, &self->pipe); if (!crtc) goto crtc_failed; retry_find_plane: if (universal_planes && drmSetClientCap (self->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) goto set_cap_failed; pres = drmModeGetPlaneResources (self->fd); if (!pres) goto plane_resources_failed; if (self->plane_id == -1) plane = find_plane_for_crtc (self->fd, res, pres, crtc->crtc_id); else plane = drmModeGetPlane (self->fd, self->plane_id); if (!plane) goto plane_failed; /* let's get the available color formats in plane */ if (!ensure_allowed_caps (self, plane, res)) goto bail; self->conn_id = conn->connector_id; self->crtc_id = crtc->crtc_id; self->plane_id = plane->plane_id; GST_INFO_OBJECT (self, "connector id = %d / crtc id = %d / plane id = %d", self->conn_id, self->crtc_id, self->plane_id); self->hdisplay = crtc->mode.hdisplay; self->vdisplay = crtc->mode.vdisplay; self->buffer_id = crtc->buffer_id; self->mm_width = conn->mmWidth; self->mm_height = conn->mmHeight; GST_INFO_OBJECT (self, "display size: pixels = %dx%d / millimeters = %dx%d", self->hdisplay, self->vdisplay, self->mm_width, self->mm_height); self->pollfd.fd = self->fd; gst_poll_add_fd (self->poll, &self->pollfd); gst_poll_fd_ctl_read (self->poll, &self->pollfd, TRUE); ret = TRUE; bail: if (plane) drmModeFreePlane (plane); if (pres) drmModeFreePlaneResources (pres); if (crtc) drmModeFreeCrtc (crtc); if (conn) drmModeFreeConnector (conn); if (res) drmModeFreeResources (res); if (!ret && self->fd >= 0) { drmClose (self->fd); self->fd = -1; } return ret; /* ERRORS */ open_failed: { GST_ERROR_OBJECT (self, "Could not open DRM module %s: %s", GST_STR_NULL (self->devname), strerror (errno)); return FALSE; } resources_failed: { GST_ERROR_OBJECT (self, "drmModeGetResources failed: %s (%d)", strerror (errno), errno); goto bail; } connector_failed: { GST_ERROR_OBJECT (self, "Could not find a valid monitor connector"); goto bail; } crtc_failed: { GST_ERROR_OBJECT (self, "Could not find a crtc for connector"); goto bail; } set_cap_failed: { GST_ERROR_OBJECT (self, "Could not set universal planes capability bit"); goto bail; } plane_resources_failed: { GST_ERROR_OBJECT (self, "drmModeGetPlaneResources failed: %s (%d)", strerror (errno), errno); goto bail; } plane_failed: { if (universal_planes) { GST_ERROR_OBJECT (self, "Could not find a plane for crtc"); goto bail; } else { universal_planes = TRUE; goto retry_find_plane; } } }
static void mess_some_more (void) { GList *walk; gint random; gint removed = 0; g_mutex_lock (fdlock); for (walk = fds; walk;) { GstPollFD *fd = (GstPollFD *) walk->data; walk = g_list_next (walk); random = (gint) (10.0 * rand () / (RAND_MAX + 1.0)); switch (random) { case 0: { /* GstPollFD *newfd = g_new0 (GstPollFD, 1); gst_poll_add_fd (set, newfd); fds = g_list_prepend (fds, newfd); */ break; } case 1: if ((gint) (10.0 * rand () / (RAND_MAX + 1.0)) < 2) { gst_poll_remove_fd (set, fd); fds = g_list_remove (fds, fd); g_free (fd); removed++; } break; case 2: gst_poll_fd_ctl_write (set, fd, TRUE); break; case 3: gst_poll_fd_ctl_write (set, fd, FALSE); break; case 4: gst_poll_fd_ctl_read (set, fd, TRUE); break; case 5: gst_poll_fd_ctl_read (set, fd, FALSE); break; case 6: gst_poll_fd_has_closed (set, fd); break; case 7: gst_poll_fd_has_error (set, fd); break; case 8: gst_poll_fd_can_read (set, fd); break; case 9: gst_poll_fd_can_write (set, fd); break; default: g_assert_not_reached (); break; } } if (g_list_length (fds) < 900) { random = removed + (gint) (2.0 * rand () / (RAND_MAX + 1.0)); while (random) { GstPollFD *newfd = g_new0 (GstPollFD, 1); gst_poll_add_fd (set, newfd); fds = g_list_prepend (fds, newfd); random--; } } g_mutex_unlock (fdlock); }
static GstFlowReturn gst_tcp_server_src_create (GstPushSrc * psrc, GstBuffer ** outbuf) { GstTCPServerSrc *src; GstFlowReturn ret = GST_FLOW_OK; src = GST_TCP_SERVER_SRC (psrc); if (!GST_OBJECT_FLAG_IS_SET (src, GST_TCP_SERVER_SRC_OPEN)) goto wrong_state; restart: if (src->client_sock_fd.fd >= 0) { /* if we have a client, wait for read */ gst_poll_fd_ctl_read (src->fdset, &src->server_sock_fd, FALSE); gst_poll_fd_ctl_read (src->fdset, &src->client_sock_fd, TRUE); } else { /* else wait on server socket for connections */ gst_poll_fd_ctl_read (src->fdset, &src->server_sock_fd, TRUE); } /* no action (0) is an error too in our case */ if ((ret = gst_poll_wait (src->fdset, GST_CLOCK_TIME_NONE)) <= 0) { if (ret == -1 && errno == EBUSY) goto select_cancelled; else goto select_error; } /* if we have no client socket we can accept one now */ if (src->client_sock_fd.fd < 0) { if (gst_poll_fd_can_read (src->fdset, &src->server_sock_fd)) { if ((src->client_sock_fd.fd = accept (src->server_sock_fd.fd, (struct sockaddr *) &src->client_sin, &src->client_sin_len)) == -1) goto accept_error; gst_poll_add_fd (src->fdset, &src->client_sock_fd); } /* and restart now to poll the socket. */ goto restart; } GST_LOG_OBJECT (src, "asked for a buffer"); switch (src->protocol) { case GST_TCP_PROTOCOL_NONE: ret = gst_tcp_read_buffer (GST_ELEMENT (src), src->client_sock_fd.fd, src->fdset, outbuf); break; case GST_TCP_PROTOCOL_GDP: if (!src->caps_received) { GstCaps *caps; gchar *string; ret = gst_tcp_gdp_read_caps (GST_ELEMENT (src), src->client_sock_fd.fd, src->fdset, &caps); if (ret == GST_FLOW_WRONG_STATE) goto gdp_cancelled; if (ret != GST_FLOW_OK) goto gdp_caps_read_error; src->caps_received = TRUE; string = gst_caps_to_string (caps); GST_DEBUG_OBJECT (src, "Received caps through GDP: %s", string); g_free (string); gst_pad_set_caps (GST_BASE_SRC_PAD (psrc), caps); } ret = gst_tcp_gdp_read_buffer (GST_ELEMENT (src), src->client_sock_fd.fd, src->fdset, outbuf); if (ret == GST_FLOW_OK) gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src))); break; default: /* need to assert as buf == NULL */ g_assert ("Unhandled protocol type"); break; } if (ret == GST_FLOW_OK) { GST_LOG_OBJECT (src, "Returning buffer from _get of size %d, ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT, GST_BUFFER_SIZE (*outbuf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*outbuf)), GST_TIME_ARGS (GST_BUFFER_DURATION (*outbuf)), GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf)); } return ret; wrong_state: { GST_DEBUG_OBJECT (src, "connection to closed, cannot read data"); return GST_FLOW_WRONG_STATE; } select_error: { GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("Select error: %s", g_strerror (errno))); return GST_FLOW_ERROR; } select_cancelled: { GST_DEBUG_OBJECT (src, "select canceled"); return GST_FLOW_WRONG_STATE; } accept_error: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Could not accept client on server socket: %s", g_strerror (errno))); return GST_FLOW_ERROR; } gdp_cancelled: { GST_DEBUG_OBJECT (src, "reading gdp canceled"); return GST_FLOW_WRONG_STATE; } gdp_caps_read_error: { /* if we did not get canceled, report an error */ if (ret != GST_FLOW_WRONG_STATE) { GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("Could not read caps through GDP")); } return ret; } }
/****************************************************** * gst_v4l2_open(): * open the video device (v4l2object->videodev) * return value: TRUE on success, FALSE on error ******************************************************/ gboolean gst_v4l2_open (GstV4l2Object * v4l2object) { struct stat st; int libv4l2_fd; GstPollFD pollfd = GST_POLL_FD_INIT; GST_DEBUG_OBJECT (v4l2object->element, "Trying to open device %s", v4l2object->videodev); GST_V4L2_CHECK_NOT_OPEN (v4l2object); GST_V4L2_CHECK_NOT_ACTIVE (v4l2object); /* be sure we have a device */ if (!v4l2object->videodev) v4l2object->videodev = g_strdup ("/dev/video"); /* check if it is a device */ if (stat (v4l2object->videodev, &st) == -1) goto stat_failed; if (!S_ISCHR (st.st_mode)) goto no_device; /* open the device */ v4l2object->video_fd = open (v4l2object->videodev, O_RDWR /* | O_NONBLOCK */ ); if (!GST_V4L2_IS_OPEN (v4l2object)) goto not_open; libv4l2_fd = v4l2_fd_open (v4l2object->video_fd, V4L2_ENABLE_ENUM_FMT_EMULATION); /* Note the v4l2_xxx functions are designed so that if they get passed an unknown fd, the will behave exactly as their regular xxx counterparts, so if v4l2_fd_open fails, we continue as normal (missing the libv4l2 custom cam format to normal formats conversion). Chances are big we will still fail then though, as normally v4l2_fd_open only fails if the device is not a v4l2 device. */ if (libv4l2_fd != -1) v4l2object->video_fd = libv4l2_fd; v4l2object->can_poll_device = TRUE; /* get capabilities, error will be posted */ if (!gst_v4l2_get_capabilities (v4l2object)) goto error; /* do we need to be a capture device? */ if (GST_IS_V4L2SRC (v4l2object->element) && !(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) goto not_capture; if (GST_IS_V4L2SINK (v4l2object->element) && !(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) goto not_output; /* create enumerations, posts errors. */ if (!gst_v4l2_fill_lists (v4l2object)) goto error; GST_INFO_OBJECT (v4l2object->element, "Opened device '%s' (%s) successfully", v4l2object->vcap.card, v4l2object->videodev); pollfd.fd = v4l2object->video_fd; gst_poll_add_fd (v4l2object->poll, &pollfd); gst_poll_fd_ctl_read (v4l2object->poll, &pollfd, TRUE); return TRUE; /* ERRORS */ stat_failed: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Cannot identify device '%s'."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } no_device: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("This isn't a device '%s'."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } not_open: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ_WRITE, (_("Could not open device '%s' for reading and writing."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } not_capture: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Device '%s' is not a capture device."), v4l2object->videodev), ("Capabilities: 0x%x", v4l2object->vcap.capabilities)); goto error; } not_output: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Device '%s' is not a output device."), v4l2object->videodev), ("Capabilities: 0x%x", v4l2object->vcap.capabilities)); goto error; } error: { if (GST_V4L2_IS_OPEN (v4l2object)) { /* close device */ v4l2_close (v4l2object->video_fd); v4l2object->video_fd = -1; } /* empty lists */ gst_v4l2_empty_lists (v4l2object); return FALSE; } }
/** * gst_v4l2_buffer_pool_new: * @obj: the v4l2 object owning the pool * * Construct a new buffer pool. * * Returns: the new pool, use gst_object_unref() to free resources */ GstBufferPool * gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps) { GstV4l2BufferPool *pool; GstStructure *config; gchar *name, *parent_name; gint fd; fd = v4l2_dup (obj->video_fd); if (fd < 0) goto dup_failed; /* setting a significant unique name */ parent_name = gst_object_get_name (GST_OBJECT (obj->element)); name = g_strconcat (parent_name, ":", "pool:", V4L2_TYPE_IS_OUTPUT (obj->type) ? "sink" : "src", NULL); g_free (parent_name); pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL, "name", name, NULL); g_free (name); gst_poll_fd_init (&pool->pollfd); pool->pollfd.fd = fd; gst_poll_add_fd (pool->poll, &pool->pollfd); if (V4L2_TYPE_IS_OUTPUT (obj->type)) gst_poll_fd_ctl_write (pool->poll, &pool->pollfd, TRUE); else gst_poll_fd_ctl_read (pool->poll, &pool->pollfd, TRUE); pool->video_fd = fd; pool->obj = obj; pool->can_poll_device = TRUE; pool->vallocator = gst_v4l2_allocator_new (GST_OBJECT (pool), obj->video_fd, &obj->format); if (pool->vallocator == NULL) goto allocator_failed; gst_object_ref (obj->element); config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool)); gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0); /* This will simply set a default config, but will not configure the pool * because min and max are not valid */ gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config); return GST_BUFFER_POOL (pool); /* ERRORS */ dup_failed: { GST_ERROR ("failed to dup fd %d (%s)", errno, g_strerror (errno)); return NULL; } allocator_failed: { GST_ERROR_OBJECT (pool, "Failed to create V4L2 allocator"); return NULL; } }