diff --git a/ChangeLog b/ChangeLog index 64947286b6..f03ce0461d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2005-07-14 Wim Taymans + + * gst/tcp/gstfdset.c: (gst_fdset_free): + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_init), + (gst_multifdsink_add), (gst_multifdsink_remove), + (gst_multifdsink_clear), (gst_multifdsink_get_stats), + (gst_multifdsink_remove_client_link), + (gst_multifdsink_client_queue_data), + (gst_multifdsink_client_queue_caps), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_queue_buffer), (gst_multifdsink_handle_clients), + (gst_multifdsink_stop): + * gst/tcp/gstmultifdsink.h: + 0.8 backporting. + + * sys/ximage/ximagesink.c: (gst_ximagesink_show_frame): + Also draw image when not from a pool. + 2005-07-14 Wim Taymans * gst/playback/gstplaybasebin.c: (check_queue), (probe_triggered), diff --git a/gst/tcp/gstfdset.c b/gst/tcp/gstfdset.c index b75510dbe9..bd9be0826b 100644 --- a/gst/tcp/gstfdset.c +++ b/gst/tcp/gstfdset.c @@ -152,6 +152,7 @@ gst_fdset_free (GstFDSet * set) case GST_FDSET_MODE_SELECT: break; case GST_FDSET_MODE_POLL: + g_free (set->testpollfds); g_free (set->pollfds); g_mutex_free (set->poll_lock); break; diff --git a/gst/tcp/gstmultifdsink.c b/gst/tcp/gstmultifdsink.c index 532e1603a9..a24ae16f09 100644 --- a/gst/tcp/gstmultifdsink.c +++ b/gst/tcp/gstmultifdsink.c @@ -409,7 +409,7 @@ gst_multifdsink_init (GstMultiFdSink * this) this->protocol = DEFAULT_PROTOCOL; this->mode = DEFAULT_MODE; - this->clientslock = g_mutex_new (); + CLIENTS_LOCK_INIT (this); this->clients = NULL; this->fd_hash = g_hash_table_new (g_int_hash, g_int_equal); @@ -453,13 +453,13 @@ gst_multifdsink_add (GstMultiFdSink * sink, int fd) /* send last activity time to connect time */ client->last_activity_time = GST_TIMEVAL_TO_TIME (now); - g_mutex_lock (sink->clientslock); + CLIENTS_LOCK (sink); /* check the hash to find a duplicate fd */ clink = g_hash_table_lookup (sink->fd_hash, &client->fd.fd); if (clink != NULL) { client->status = GST_CLIENT_STATUS_DUPLICATE; - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); GST_WARNING_OBJECT (sink, "[fd %5d] duplicate client found, refusing", fd); g_signal_emit (G_OBJECT (sink), gst_multifdsink_signals[SIGNAL_CLIENT_REMOVED], 0, fd, client->status); @@ -489,7 +489,7 @@ gst_multifdsink_add (GstMultiFdSink * sink, int fd) SEND_COMMAND (sink, CONTROL_RESTART); - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); g_signal_emit (G_OBJECT (sink), gst_multifdsink_signals[SIGNAL_CLIENT_ADDED], 0, fd); @@ -502,7 +502,7 @@ gst_multifdsink_remove (GstMultiFdSink * sink, int fd) GST_DEBUG_OBJECT (sink, "[fd %5d] removing client", fd); - g_mutex_lock (sink->clientslock); + CLIENTS_LOCK (sink); clink = g_hash_table_lookup (sink->fd_hash, &fd); if (clink != NULL) { GstTCPClient *client = (GstTCPClient *) clink->data; @@ -513,7 +513,7 @@ gst_multifdsink_remove (GstMultiFdSink * sink, int fd) } else { GST_WARNING_OBJECT (sink, "[fd %5d] no client with this fd found!", fd); } - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); } void @@ -523,7 +523,7 @@ gst_multifdsink_clear (GstMultiFdSink * sink) GST_DEBUG_OBJECT (sink, "clearing all clients"); - g_mutex_lock (sink->clientslock); + CLIENTS_LOCK (sink); for (clients = sink->clients; clients; clients = next) { GstTCPClient *client; @@ -534,7 +534,7 @@ gst_multifdsink_clear (GstMultiFdSink * sink) gst_multifdsink_remove_client_link (sink, clients); } SEND_COMMAND (sink, CONTROL_RESTART); - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); } GValueArray * @@ -544,7 +544,7 @@ gst_multifdsink_get_stats (GstMultiFdSink * sink, int fd) GValueArray *result = NULL; GList *clink; - g_mutex_lock (sink->clientslock); + CLIENTS_LOCK (sink); clink = g_hash_table_lookup (sink->fd_hash, &fd); client = (GstTCPClient *) clink->data; if (client != NULL) { @@ -582,7 +582,7 @@ gst_multifdsink_get_stats (GstMultiFdSink * sink, int fd) g_value_set_uint64 (&value, client->last_activity_time); result = g_value_array_append (result, &value); } - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); /* python doesn't like a NULL pointer yet */ if (result == NULL) { @@ -650,19 +650,24 @@ gst_multifdsink_remove_client_link (GstMultiFdSink * sink, GList * link) /* unlock the mutex before signaling because the signal handler * might query some properties */ - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); g_signal_emit (G_OBJECT (sink), gst_multifdsink_signals[SIGNAL_CLIENT_REMOVED], 0, fd, client->status); /* lock again before we remove the client completely */ - g_mutex_lock (sink->clientslock); + CLIENTS_LOCK (sink); if (!g_hash_table_remove (sink->fd_hash, &client->fd.fd)) { GST_WARNING_OBJECT (sink, "[fd %5d] error removing client %p from hash", client->fd.fd, client); } - sink->clients = g_list_delete_link (sink->clients, link); + /* after releasing the lock above, the link could be invalid, more + * precisely, the next and prev pointers could point to invalid list + * links. One optimisation could be to add a cookie to the linked list + * and take a shortcut when it did not change between unlocking and locking + * our mutex. For now we just walk the list again. */ + sink->clients = g_list_remove (sink->clients, client); if (fclass->removed) fclass->removed (sink, client->fd.fd); @@ -740,12 +745,12 @@ gst_multifdsink_handle_client_read (GstMultiFdSink * sink, static gboolean gst_multifdsink_client_queue_data (GstMultiFdSink * sink, GstTCPClient * client, - guint8 * data, gint len) + gchar * data, gint len) { GstBuffer *buf; buf = gst_buffer_new (); - GST_BUFFER_DATA (buf) = data; + GST_BUFFER_DATA (buf) = (guint8 *) data; GST_BUFFER_SIZE (buf) = len; GST_LOG_OBJECT (sink, "[fd %5d] queueing data of length %d", @@ -774,10 +779,10 @@ gst_multifdsink_client_queue_caps (GstMultiFdSink * sink, GstTCPClient * client, GST_DEBUG_OBJECT (sink, "Could not create GDP packet from caps"); return FALSE; } - gst_multifdsink_client_queue_data (sink, client, header, length); + gst_multifdsink_client_queue_data (sink, client, (gchar *) header, length); length = gst_dp_header_payload_length (header); - gst_multifdsink_client_queue_data (sink, client, payload, length); + gst_multifdsink_client_queue_data (sink, client, (gchar *) payload, length); return TRUE; } @@ -806,7 +811,7 @@ gst_multifdsink_client_queue_buffer (GstMultiFdSink * sink, "[fd %5d] could not create header, removing client", client->fd.fd); return FALSE; } - gst_multifdsink_client_queue_data (sink, client, header, len); + gst_multifdsink_client_queue_data (sink, client, (gchar *) header, len); } GST_LOG_OBJECT (sink, "[fd %5d] queueing buffer of length %d", @@ -1171,7 +1176,7 @@ gst_multifdsink_queue_buffer (GstMultiFdSink * sink, GstBuffer * buf) g_get_current_time (&nowtv); now = GST_TIMEVAL_TO_TIME (nowtv); - g_mutex_lock (sink->clientslock); + CLIENTS_LOCK (sink); /* add buffer to queue */ g_array_prepend_val (sink->bufqueue, buf); queuelen = sink->bufqueue->len; @@ -1271,7 +1276,7 @@ gst_multifdsink_queue_buffer (GstMultiFdSink * sink, GstBuffer * buf) } /* save for stats */ sink->buffers_queued = max_buffer_usage; - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); /* and send a signal to thread if fd_set changed */ if (need_signal) { @@ -1316,7 +1321,7 @@ gst_multifdsink_handle_clients (GstMultiFdSink * sink) if (errno == EBADF) { /* ok, so one or more of the fds is invalid. We loop over them to find * the ones that give an error to the F_GETFL fcntl. */ - g_mutex_lock (sink->clientslock); + CLIENTS_LOCK (sink); for (clients = sink->clients; clients; clients = next) { GstTCPClient *client; int fd; @@ -1338,7 +1343,7 @@ gst_multifdsink_handle_clients (GstMultiFdSink * sink) } } } - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); /* after this, go back in the select loop as the read/writefds * are not valid */ try_again = TRUE; @@ -1400,7 +1405,7 @@ gst_multifdsink_handle_clients (GstMultiFdSink * sink) fclass->wait (sink, sink->fdset); /* Check the clients */ - g_mutex_lock (sink->clientslock); + CLIENTS_LOCK (sink); for (clients = sink->clients; clients; clients = next) { GstTCPClient *client; @@ -1438,7 +1443,7 @@ gst_multifdsink_handle_clients (GstMultiFdSink * sink) } } } - g_mutex_unlock (sink->clientslock); + CLIENTS_UNLOCK (sink); } /* we handle the client communication in another thread so that we do not block @@ -1717,6 +1722,8 @@ gst_multifdsink_stop (GstBaseSink * bsink) this->fdset = NULL; } GST_FLAG_UNSET (this, GST_MULTIFDSINK_OPEN); + CLIENTS_LOCK_FREE (this); + g_hash_table_destroy (this->fd_hash); return TRUE; } diff --git a/gst/tcp/gstmultifdsink.h b/gst/tcp/gstmultifdsink.h index 00828dfa19..680c182c3b 100644 --- a/gst/tcp/gstmultifdsink.h +++ b/gst/tcp/gstmultifdsink.h @@ -116,13 +116,18 @@ typedef struct { } GstTCPClient; +#define CLIENTS_LOCK_INIT(fdsink) (g_static_rec_mutex_init(&fdsink->clientslock)) +#define CLIENTS_LOCK_FREE(fdsink) (g_static_rec_mutex_free(&fdsink->clientslock)) +#define CLIENTS_LOCK(fdsink) (g_static_rec_mutex_lock(&fdsink->clientslock)) +#define CLIENTS_UNLOCK(fdsink) (g_static_rec_mutex_unlock(&fdsink->clientslock)) + struct _GstMultiFdSink { GstBaseSink element; guint64 bytes_to_serve; /* how much bytes we must serve */ guint64 bytes_served; /* how much bytes have we served */ - GMutex *clientslock; /* lock to protect the clients list */ + GStaticRecMutex clientslock; /* lock to protect the clients list */ GList *clients; /* list of clients we are serving */ GHashTable *fd_hash; /* index on fd to client */ diff --git a/sys/ximage/ximagesink.c b/sys/ximage/ximagesink.c index 7f0c382153..20e5b4d38b 100644 --- a/sys/ximage/ximagesink.c +++ b/sys/ximage/ximagesink.c @@ -1234,18 +1234,13 @@ gst_ximagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf) ximagesink->ximage = gst_ximagesink_ximage_new (ximagesink, GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink)); - if (!ximagesink->ximage) { - /* No image available. That's very bad ! */ - gst_buffer_unref (buf); - GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL), - ("Failed creating an XImage in ximagesink chain function.")); - return GST_FLOW_ERROR; - } - memcpy (ximagesink->ximage->ximage->data, - GST_BUFFER_DATA (buf), - MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size)); - gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage); + if (!ximagesink->ximage) + goto no_ximage; } + memcpy (ximagesink->ximage->ximage->data, + GST_BUFFER_DATA (buf), + MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size)); + gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage); } gst_ximagesink_handle_xevents (ximagesink); @@ -1256,6 +1251,17 @@ gst_ximagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf) g_mutex_unlock (ximagesink->stream_lock); return GST_FLOW_OK; + + /* ERRORS */ +no_ximage: + { + /* No image available. That's very bad ! */ + g_mutex_unlock (ximagesink->stream_lock); + gst_buffer_unref (buf); + GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL), + ("Failed creating an XImage in ximagesink chain function.")); + return GST_FLOW_ERROR; + } } /* Buffer management */