diff --git a/ChangeLog b/ChangeLog index e9ce8523b8..73174f17cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-01-29 Ronald S. Bultje + + * gst/elements/gstfdsrc.c: (gst_fdsrc_init), + (gst_fdsrc_get_query_types), (gst_fdsrc_get_formats), + (gst_fdsrc_srcpad_query): + Implement querying. + * gst/gstqueue.c: (gst_queue_chain), (gst_queue_get): + If we're waiting to be "full enough to start" and EOS comes in, + just flow through all data since waiting longer is not going to + help us. Fixes hangs on short media files played from network + sources. + * gst/gsttag.c: (_gst_tag_initialize): + * gst/gsttag.h: + Add GST_TAG_IMAGE tag. + 2006-01-14 Thomas Vander Stichele * docs/manual/Makefile.am: diff --git a/common b/common index e0b121388e..bc4325349e 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit e0b121388ece524c0b7035a72bddd191d122d8bf +Subproject commit bc4325349e8d0ec90aa5c5e74566880cc2e82527 diff --git a/gst/elements/gstfdsrc.c b/gst/elements/gstfdsrc.c index fdeac10707..a88fb51fb6 100644 --- a/gst/elements/gstfdsrc.c +++ b/gst/elements/gstfdsrc.c @@ -103,6 +103,11 @@ static void gst_fdsrc_set_property (GObject * object, guint prop_id, static void gst_fdsrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static const GstQueryType *gst_fdsrc_get_query_types (GstPad * pad); +static const GstFormat *gst_fdsrc_get_formats (GstPad * pad); +static gboolean gst_fdsrc_srcpad_query (GstPad * pad, GstQueryType type, + GstFormat * fmt, gint64 * value); + static GstElementStateReturn gst_fdsrc_change_state (GstElement * element); static gboolean gst_fdsrc_release_locks (GstElement * element); static GstData *gst_fdsrc_get (GstPad * pad); @@ -168,6 +173,9 @@ gst_fdsrc_init (GstFdSrc * fdsrc) "src"); gst_pad_set_get_function (fdsrc->srcpad, gst_fdsrc_get); + gst_pad_set_query_function (fdsrc->srcpad, gst_fdsrc_srcpad_query); + gst_pad_set_query_type_function (fdsrc->srcpad, gst_fdsrc_get_query_types); + gst_pad_set_formats_function (fdsrc->srcpad, gst_fdsrc_get_formats); gst_element_add_pad (GST_ELEMENT (fdsrc), fdsrc->srcpad); fdsrc->fd = 0; @@ -178,6 +186,42 @@ gst_fdsrc_init (GstFdSrc * fdsrc) fdsrc->seq = 0; } +static const GstQueryType * +gst_fdsrc_get_query_types (GstPad * pad) +{ + static const GstQueryType types[] = { + GST_QUERY_POSITION, + 0 + }; + + return types; +} + +static const GstFormat * +gst_fdsrc_get_formats (GstPad * pad) +{ + static const GstFormat formats[] = { + GST_FORMAT_BYTES, + 0, + }; + + return formats; +} + +static gboolean +gst_fdsrc_srcpad_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * value) +{ + GstFdSrc *fdsrc = GST_FDSRC (gst_pad_get_parent (pad)); + + if (*format != GST_FORMAT_BYTES || type != GST_QUERY_POSITION) + return FALSE; + + *value = fdsrc->curoffset; + + return TRUE; +} + static GstElementStateReturn gst_fdsrc_change_state (GstElement * element) { diff --git a/gst/gstqueue.c b/gst/gstqueue.c index 0d388cf5a4..1b46973922 100644 --- a/gst/gstqueue.c +++ b/gst/gstqueue.c @@ -59,6 +59,21 @@ GST_DEBUG_CATEGORY_STATIC (queue_dataflow); queue->min_threshold.time, \ queue->max_size.time, \ queue->queue->length) +#define IS_FULL(queue) \ + ((queue->max_size.buffers > 0 && \ + queue->cur_level.buffers >= queue->max_size.buffers) || \ + (queue->max_size.bytes > 0 && \ + queue->cur_level.bytes >= queue->max_size.bytes) || \ + (queue->max_size.time > 0 && \ + queue->cur_level.time >= queue->max_size.time)) +#define IS_EMPTY(queue) \ + (queue->queue->length == 0 || \ + (queue->min_threshold.buffers > 0 && \ + queue->cur_level.buffers < queue->min_threshold.buffers) || \ + (queue->min_threshold.bytes > 0 && \ + queue->cur_level.bytes < queue->min_threshold.bytes) || \ + (queue->min_threshold.time > 0 && \ + queue->cur_level.time < queue->min_threshold.time)) static GstElementDetails gst_queue_details = GST_ELEMENT_DETAILS ("Queue", "Generic", @@ -592,14 +607,10 @@ restart: * and filler events with a duration * We always handle events and they don't count in our statistics. */ if ((GST_IS_BUFFER (data) || - (GST_IS_EVENT (data) && GST_EVENT_TYPE (data) == GST_EVENT_FILLER && + (GST_IS_EVENT (data) && + GST_EVENT_TYPE (data) == GST_EVENT_FILLER && gst_event_filler_get_duration (GST_EVENT (data)) != - GST_CLOCK_TIME_NONE)) && ((queue->max_size.buffers > 0 - && queue->cur_level.buffers >= queue->max_size.buffers) - || (queue->max_size.bytes > 0 - && queue->cur_level.bytes >= queue->max_size.bytes) - || (queue->max_size.time > 0 - && queue->cur_level.time >= queue->max_size.time))) { + GST_CLOCK_TIME_NONE)) && IS_FULL (queue)) { GST_QUEUE_MUTEX_UNLOCK; g_signal_emit (G_OBJECT (queue), gst_queue_signals[SIGNAL_OVERRUN], 0); GST_QUEUE_MUTEX_LOCK; @@ -663,12 +674,7 @@ restart: case GST_QUEUE_NO_LEAK: STATUS (queue, "pre-full wait"); - while ((queue->max_size.buffers > 0 && - queue->cur_level.buffers >= queue->max_size.buffers) || - (queue->max_size.bytes > 0 && - queue->cur_level.bytes >= queue->max_size.bytes) || - (queue->max_size.time > 0 && - queue->cur_level.time >= queue->max_size.time)) { + while (IS_FULL (queue)) { /* if there's a pending state change for this queue * or its manager, switch back to iterator so bottom * half of state change executes */ @@ -793,25 +799,27 @@ restart: /* have to lock for thread-safety */ GST_QUEUE_MUTEX_LOCK; - if (queue->queue->length == 0 || - (queue->min_threshold.buffers > 0 && - queue->cur_level.buffers < queue->min_threshold.buffers) || - (queue->min_threshold.bytes > 0 && - queue->cur_level.bytes < queue->min_threshold.bytes) || - (queue->min_threshold.time > 0 && - queue->cur_level.time < queue->min_threshold.time)) { + if (IS_EMPTY (queue)) { GST_QUEUE_MUTEX_UNLOCK; g_signal_emit (G_OBJECT (queue), gst_queue_signals[SIGNAL_UNDERRUN], 0); GST_QUEUE_MUTEX_LOCK; STATUS (queue, "pre-empty wait"); - while (queue->queue->length == 0 || - (queue->min_threshold.buffers > 0 && - queue->cur_level.buffers < queue->min_threshold.buffers) || - (queue->min_threshold.bytes > 0 && - queue->cur_level.bytes < queue->min_threshold.bytes) || - (queue->min_threshold.time > 0 && - queue->cur_level.time < queue->min_threshold.time)) { + while (IS_EMPTY (queue)) { + /* if there's an EOS in the queue, just run */ + GList *item; + gboolean got_eos = FALSE; + + for (item = queue->queue->head; item != NULL; item = item->next) { + if (GST_IS_EVENT (item->data) && + GST_EVENT_TYPE (item->data) == GST_EVENT_EOS) { + GST_CAT_DEBUG (queue_dataflow, "got eos, exit loop"); + got_eos = TRUE; + break; + } + } + if (got_eos) + break; /* if there's a pending state change for this queue or its * manager, switch back to iterator so bottom half of state * change executes. */ diff --git a/gst/gsttag.c b/gst/gsttag.c index 28ab69fd37..a159e753f9 100644 --- a/gst/gsttag.c +++ b/gst/gsttag.c @@ -25,6 +25,7 @@ #include "gst_private.h" #include "gst-i18n-lib.h" +#include "gstbuffer.h" #include "gsttag.h" #include "gstinfo.h" #include "gstvalue.h" @@ -191,6 +192,8 @@ _gst_tag_initialize (void) gst_tag_register (GST_TAG_LANGUAGE_CODE, GST_TAG_FLAG_META, G_TYPE_STRING, _("language code"), _("language code for this stream, conforming to ISO-639-1"), NULL); + gst_tag_register (GST_TAG_IMAGE, GST_TAG_FLAG_META, GST_TYPE_BUFFER, + _("image"), _("cover art or image for screenshot display"), NULL); } /** diff --git a/gst/gsttag.h b/gst/gsttag.h index f7bca61aba..d7c24cd664 100644 --- a/gst/gsttag.h +++ b/gst/gsttag.h @@ -436,6 +436,13 @@ GstTagList * gst_event_tag_get_list (GstEvent * tag_event); * Language code (ISO-639-1) */ #define GST_TAG_LANGUAGE_CODE "language-code" +/** + * GST_TAG_IMAGE: + * + * Image, such as cover art or screenshot in movie (if explicitely + * supplied in media) + */ +#define GST_TAG_IMAGE "image" G_END_DECLS