mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
gst/base/gstbasesrc.c: Don't go in pull mode for non-seekable sources.
Original commit message from CVS: * gst/base/gstbasesrc.c: (gst_basesrc_activate): Don't go in pull mode for non-seekable sources. * gst/elements/gsttypefindelement.c: (gst_type_find_element_init), (gst_type_find_element_dispose), (gst_type_find_handle_src_query), (free_entry), (stop_typefinding), (gst_type_find_element_handle_event), (find_peek), (gst_type_find_element_chain), (do_pull_typefind), (gst_type_find_element_change_state): Allow typefinding (w/o seeking) in push-mode, simplified version of what was in 0.8. * gst/gstutils.c: (gst_buffer_join): * gst/gstutils.h: gst_buffer_join() from 0.8.
This commit is contained in:
parent
25576cb626
commit
f0ed41684a
7 changed files with 217 additions and 364 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
||||||
|
2005-05-25 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
|
* gst/base/gstbasesrc.c: (gst_basesrc_activate):
|
||||||
|
Don't go in pull mode for non-seekable sources.
|
||||||
|
* gst/elements/gsttypefindelement.c: (gst_type_find_element_init),
|
||||||
|
(gst_type_find_element_dispose), (gst_type_find_handle_src_query),
|
||||||
|
(free_entry), (stop_typefinding),
|
||||||
|
(gst_type_find_element_handle_event), (find_peek),
|
||||||
|
(gst_type_find_element_chain), (do_pull_typefind),
|
||||||
|
(gst_type_find_element_change_state):
|
||||||
|
Allow typefinding (w/o seeking) in push-mode, simplified version
|
||||||
|
of what was in 0.8.
|
||||||
|
* gst/gstutils.c: (gst_buffer_join):
|
||||||
|
* gst/gstutils.h:
|
||||||
|
gst_buffer_join() from 0.8.
|
||||||
|
|
||||||
2005-05-25 Wim Taymans <wim@fluendo.com>
|
2005-05-25 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
|
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
|
||||||
|
|
|
@ -716,7 +716,9 @@ gst_basesrc_activate (GstPad * pad, GstActivateMode mode)
|
||||||
gst_pad_start_task (pad, (GstTaskFunction) gst_basesrc_loop, pad);
|
gst_pad_start_task (pad, (GstTaskFunction) gst_basesrc_loop, pad);
|
||||||
break;
|
break;
|
||||||
case GST_ACTIVATE_PULL:
|
case GST_ACTIVATE_PULL:
|
||||||
result = TRUE;
|
result = basesrc->seekable;
|
||||||
|
if (!result)
|
||||||
|
gst_basesrc_stop (basesrc);
|
||||||
break;
|
break;
|
||||||
case GST_ACTIVATE_NONE:
|
case GST_ACTIVATE_NONE:
|
||||||
/* step 1, unblock clock sync (if any) */
|
/* step 1, unblock clock sync (if any) */
|
||||||
|
|
|
@ -122,7 +122,6 @@ static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
|
||||||
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
|
static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
|
||||||
static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind);
|
|
||||||
|
|
||||||
static gboolean gst_type_find_element_handle_event (GstPad * pad,
|
static gboolean gst_type_find_element_handle_event (GstPad * pad,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
|
@ -226,11 +225,12 @@ gst_type_find_element_init (GstTypeFindElement * typefind)
|
||||||
gst_pad_use_fixed_caps (typefind->src);
|
gst_pad_use_fixed_caps (typefind->src);
|
||||||
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
||||||
|
|
||||||
|
typefind->mode = MODE_TYPEFIND;
|
||||||
typefind->caps = NULL;
|
typefind->caps = NULL;
|
||||||
typefind->min_probability = 1;
|
typefind->min_probability = 1;
|
||||||
typefind->max_probability = GST_TYPE_FIND_MAXIMUM;
|
typefind->max_probability = GST_TYPE_FIND_MAXIMUM;
|
||||||
|
|
||||||
typefind->store = gst_buffer_store_new ();
|
typefind->store = NULL;
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
gst_type_find_element_dispose (GObject * object)
|
gst_type_find_element_dispose (GObject * object)
|
||||||
|
@ -240,7 +240,7 @@ gst_type_find_element_dispose (GObject * object)
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
|
||||||
if (typefind->store) {
|
if (typefind->store) {
|
||||||
g_object_unref (typefind->store);
|
gst_buffer_unref (typefind->store);
|
||||||
typefind->store = NULL;
|
typefind->store = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,7 @@ gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
|
||||||
/* FIXME: this code assumes that there's no discont in the queue */
|
/* FIXME: this code assumes that there's no discont in the queue */
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
peer_pos -= gst_buffer_store_get_size (typefind->store, 0);
|
peer_pos -= typefind->store->size;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
|
@ -369,10 +369,7 @@ typedef struct
|
||||||
GstTypeFindFactory *factory;
|
GstTypeFindFactory *factory;
|
||||||
gint probability;
|
gint probability;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
gint64 requested_offset;
|
|
||||||
guint requested_size;
|
guint requested_size;
|
||||||
|
|
||||||
GList *buffers;
|
|
||||||
GstTypeFindElement *self;
|
GstTypeFindElement *self;
|
||||||
}
|
}
|
||||||
TypeFindEntry;
|
TypeFindEntry;
|
||||||
|
@ -383,17 +380,8 @@ new_entry (void)
|
||||||
return g_new0 (TypeFindEntry, 1);
|
return g_new0 (TypeFindEntry, 1);
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
free_entry_buffers (TypeFindEntry * entry)
|
|
||||||
{
|
|
||||||
g_list_foreach (entry->buffers, (GFunc) gst_mini_object_unref, NULL);
|
|
||||||
g_list_free (entry->buffers);
|
|
||||||
entry->buffers = NULL;
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
free_entry (TypeFindEntry * entry)
|
free_entry (TypeFindEntry * entry)
|
||||||
{
|
{
|
||||||
free_entry_buffers (entry);
|
|
||||||
|
|
||||||
if (entry->caps)
|
if (entry->caps)
|
||||||
gst_caps_unref (entry->caps);
|
gst_caps_unref (entry->caps);
|
||||||
g_free (entry);
|
g_free (entry);
|
||||||
|
@ -416,8 +404,6 @@ static void
|
||||||
stop_typefinding (GstTypeFindElement * typefind)
|
stop_typefinding (GstTypeFindElement * typefind)
|
||||||
{
|
{
|
||||||
GstElementState state;
|
GstElementState state;
|
||||||
|
|
||||||
/* stop all typefinding and set mode back to normal */
|
|
||||||
gboolean push_cached_buffers;
|
gboolean push_cached_buffers;
|
||||||
|
|
||||||
gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, NULL);
|
gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, NULL);
|
||||||
|
@ -436,35 +422,17 @@ stop_typefinding (GstTypeFindElement * typefind)
|
||||||
}
|
}
|
||||||
//typefind->mode = MODE_TRANSITION;
|
//typefind->mode = MODE_TRANSITION;
|
||||||
|
|
||||||
if (!push_cached_buffers) {
|
if (typefind->store) {
|
||||||
gst_buffer_store_clear (typefind->store);
|
if (!push_cached_buffers) {
|
||||||
} else {
|
gst_buffer_unref (typefind->store);
|
||||||
typefind->mode = MODE_NORMAL;
|
} else {
|
||||||
/* push out our queued buffers here */
|
typefind->mode = MODE_NORMAL;
|
||||||
push_buffer_store (typefind);
|
gst_pad_push (typefind->src, typefind->store);
|
||||||
|
}
|
||||||
|
typefind->store = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
push_buffer_store (GstTypeFindElement * typefind)
|
|
||||||
{
|
|
||||||
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
|
||||||
GstBuffer *buffer;
|
|
||||||
GstFlowReturn ret;
|
|
||||||
|
|
||||||
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
|
||||||
GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
|
|
||||||
ret = gst_pad_push (typefind->src, buffer);
|
|
||||||
} else {
|
|
||||||
size = 0;
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_buffer_store_clear (typefind->store);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint64
|
static guint64
|
||||||
find_element_get_length (gpointer data)
|
find_element_get_length (gpointer data)
|
||||||
{
|
{
|
||||||
|
@ -529,7 +497,8 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
|
||||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||||
0, entry->probability, entry->caps);
|
0, entry->probability, entry->caps);
|
||||||
stop_typefinding (typefind);
|
stop_typefinding (typefind);
|
||||||
push_buffer_store (typefind);
|
gst_pad_push (typefind->src, typefind->store);
|
||||||
|
typefind->store = NULL;
|
||||||
res = gst_pad_event_default (pad, event);
|
res = gst_pad_event_default (pad, event);
|
||||||
} else {
|
} else {
|
||||||
res = gst_pad_event_default (pad, event);
|
res = gst_pad_event_default (pad, event);
|
||||||
|
@ -561,37 +530,21 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
|
||||||
static guint8 *
|
static guint8 *
|
||||||
find_peek (gpointer data, gint64 offset, guint size)
|
find_peek (gpointer data, gint64 offset, guint size)
|
||||||
{
|
{
|
||||||
GstBuffer *buf;
|
|
||||||
TypeFindEntry *entry = (TypeFindEntry *) data;
|
TypeFindEntry *entry = (TypeFindEntry *) data;
|
||||||
|
|
||||||
GST_LOG_OBJECT (entry->self, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
|
GST_LOG_OBJECT (entry->self, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory), offset, size);
|
GST_PLUGIN_FEATURE_NAME (entry->factory), offset, size);
|
||||||
if (offset >= 0) {
|
if (offset != 0)
|
||||||
buf = gst_buffer_store_get_buffer (entry->self->store, offset, size);
|
return NULL;
|
||||||
} else {
|
|
||||||
/* FIXME: can we do this easily without querying length? */
|
|
||||||
guint64 length = find_element_get_length (data);
|
|
||||||
|
|
||||||
if (length < -offset) {
|
if (size <= entry->self->store->size) {
|
||||||
buf = NULL;
|
return GST_BUFFER_DATA (entry->self->store);
|
||||||
} else {
|
|
||||||
buf =
|
|
||||||
gst_buffer_store_get_buffer (entry->self->store, length + offset,
|
|
||||||
size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf) {
|
|
||||||
entry->buffers = g_list_prepend (entry->buffers, buf);
|
|
||||||
return GST_BUFFER_DATA (buf);
|
|
||||||
} else {
|
} else {
|
||||||
if (entry->requested_size == 0) {
|
entry->requested_size = size;
|
||||||
GST_LOG_OBJECT (entry->self,
|
|
||||||
"setting requested peek (%" G_GINT64_FORMAT ", %u) on '%s'", offset,
|
GST_LOG_OBJECT (entry->self,
|
||||||
size, GST_PLUGIN_FEATURE_NAME (entry->factory));
|
"setting requested peek (%" G_GINT64_FORMAT ", %u) on '%s'", offset,
|
||||||
entry->requested_offset = offset;
|
size, GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||||
entry->requested_size = size;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,6 +561,7 @@ find_suggest (gpointer data, guint probability, const GstCaps * caps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static gint
|
static gint
|
||||||
compare_type_find_entry (gconstpointer a, gconstpointer b)
|
compare_type_find_entry (gconstpointer a, gconstpointer b)
|
||||||
{
|
{
|
||||||
|
@ -621,6 +575,7 @@ compare_type_find_entry (gconstpointer a, gconstpointer b)
|
||||||
return two->probability - one->probability;
|
return two->probability - one->probability;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
compare_type_find_factory (gconstpointer fac1, gconstpointer fac2)
|
compare_type_find_factory (gconstpointer fac1, gconstpointer fac2)
|
||||||
|
@ -644,20 +599,19 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
case MODE_NORMAL:
|
case MODE_NORMAL:
|
||||||
return gst_pad_push (typefind->src, buffer);
|
return gst_pad_push (typefind->src, buffer);
|
||||||
case MODE_TYPEFIND:{
|
case MODE_TYPEFIND:{
|
||||||
guint64 current_offset;
|
gboolean done = TRUE;
|
||||||
|
|
||||||
gst_buffer_store_add_buffer (typefind->store, buffer);
|
if (typefind->store)
|
||||||
current_offset = GST_BUFFER_OFFSET_IS_VALID (buffer) ?
|
typefind->store = gst_buffer_join (typefind->store, buffer);
|
||||||
GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) :
|
else
|
||||||
gst_buffer_store_get_size (typefind->store, 0);
|
typefind->store = buffer;
|
||||||
gst_buffer_unref (buffer);
|
|
||||||
|
|
||||||
if (typefind->possibilities == NULL) {
|
if (typefind->possibilities == NULL) {
|
||||||
/* not yet started, get all typefinding functions into our "queue" */
|
/* not yet started, get all typefinding functions into our "queue" */
|
||||||
GList *all_factories = gst_type_find_factory_get_list ();
|
GList *all_factories = gst_type_find_factory_get_list ();
|
||||||
|
|
||||||
GST_INFO_OBJECT (typefind, "starting with %u typefinding functions",
|
GST_INFO_OBJECT (typefind, "starting with %u typefinding functions",
|
||||||
g_list_length ((GList *) all_factories));
|
g_list_length (all_factories));
|
||||||
|
|
||||||
all_factories = g_list_sort (all_factories, compare_type_find_factory);
|
all_factories = g_list_sort (all_factories, compare_type_find_factory);
|
||||||
walk = all_factories;
|
walk = all_factories;
|
||||||
|
@ -673,6 +627,7 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
}
|
}
|
||||||
g_list_free (all_factories);
|
g_list_free (all_factories);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call every typefind function once */
|
/* call every typefind function once */
|
||||||
walk = entries = typefind->possibilities;
|
walk = entries = typefind->possibilities;
|
||||||
GST_INFO_OBJECT (typefind, "iterating %u typefinding functions",
|
GST_INFO_OBJECT (typefind, "iterating %u typefinding functions",
|
||||||
|
@ -681,11 +636,14 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
while (walk) {
|
while (walk) {
|
||||||
find.data = entry = (TypeFindEntry *) walk->data;
|
find.data = entry = (TypeFindEntry *) walk->data;
|
||||||
walk = g_list_next (walk);
|
walk = g_list_next (walk);
|
||||||
entry->probability = 0;
|
if (entry->probability == 0) {
|
||||||
entry->requested_offset = 0;
|
entry->requested_size = 0;
|
||||||
entry->requested_size = 0;
|
gst_type_find_factory_call_function (entry->factory, &find);
|
||||||
gst_type_find_factory_call_function (entry->factory, &find);
|
} else {
|
||||||
free_entry_buffers (entry);
|
typefind->possibilities =
|
||||||
|
g_list_prepend (typefind->possibilities, entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (entry->probability == 0 && entry->requested_size == 0) {
|
if (entry->probability == 0 && entry->requested_size == 0) {
|
||||||
GST_DEBUG_OBJECT (typefind,
|
GST_DEBUG_OBJECT (typefind,
|
||||||
"'%s' was removed - no chance of being the right plugin",
|
"'%s' was removed - no chance of being the right plugin",
|
||||||
|
@ -709,113 +667,54 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
free_entry (walk->data);
|
free_entry (walk->data);
|
||||||
walk = g_list_next (walk);
|
walk = g_list_next (walk);
|
||||||
}
|
}
|
||||||
typefind->possibilities = NULL;
|
|
||||||
g_list_free (typefind->possibilities);
|
g_list_free (typefind->possibilities);
|
||||||
|
typefind->possibilities = NULL;
|
||||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
|
||||||
probability, found_caps);
|
probability, found_caps);
|
||||||
free_entry (entry);
|
free_entry (entry);
|
||||||
} else {
|
} else {
|
||||||
typefind->possibilities =
|
typefind->possibilities =
|
||||||
g_list_prepend (typefind->possibilities, entry);
|
g_list_prepend (typefind->possibilities, entry);
|
||||||
|
if (entry->requested_size != 0)
|
||||||
|
done = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_list_free (entries);
|
g_list_free (entries);
|
||||||
|
|
||||||
/* we may now already have caps or we might be left without functions to try */
|
/* we may now already have caps or we might be left without functions to try */
|
||||||
if (typefind->caps) {
|
if (typefind->caps) {
|
||||||
stop_typefinding (typefind);
|
stop_typefinding (typefind);
|
||||||
} else if (typefind->possibilities == NULL) {
|
} else if (typefind->possibilities == NULL) {
|
||||||
error:
|
|
||||||
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
||||||
stop_typefinding (typefind);
|
stop_typefinding (typefind);
|
||||||
} else {
|
return GST_FLOW_ERROR;
|
||||||
/* set up typefind element for next iteration */
|
} else if (done) {
|
||||||
typefind->possibilities =
|
TypeFindEntry *best = NULL;
|
||||||
g_list_sort (typefind->possibilities, compare_type_find_entry);
|
|
||||||
|
|
||||||
/* look for typefind functions that require data without seeking */
|
walk = typefind->possibilities;
|
||||||
for (walk = typefind->possibilities; walk; walk = g_list_next (walk)) {
|
|
||||||
entry = (TypeFindEntry *) walk->data;
|
|
||||||
if (entry->requested_offset <= current_offset &&
|
|
||||||
entry->requested_offset + entry->requested_size > current_offset)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!walk) {
|
|
||||||
/* find out if we should seek */
|
|
||||||
restart:
|
|
||||||
for (walk = typefind->possibilities; walk; walk = g_list_next (walk)) {
|
|
||||||
entry = (TypeFindEntry *) walk->data;
|
|
||||||
if (entry->requested_size > 0) {
|
|
||||||
/* FIXME: need heuristic to find out if we should seek */
|
|
||||||
gint64 seek_offset;
|
|
||||||
GstEvent *event;
|
|
||||||
|
|
||||||
seek_offset =
|
|
||||||
entry->requested_offset >
|
|
||||||
0 ? entry->
|
|
||||||
requested_offset : find_element_get_length (entry) +
|
|
||||||
entry->requested_offset;
|
|
||||||
seek_offset +=
|
|
||||||
gst_buffer_store_get_size (typefind->store, seek_offset);
|
|
||||||
event =
|
|
||||||
gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET,
|
|
||||||
seek_offset);
|
|
||||||
if (gst_pad_send_event (GST_PAD_PEER (typefind->sink), event)) {
|
|
||||||
/* done seeking */
|
|
||||||
GST_DEBUG_OBJECT (typefind,
|
|
||||||
"'%s' was reset - seeked to %" G_GINT64_FORMAT,
|
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory), seek_offset);
|
|
||||||
break;
|
|
||||||
} else if (entry->requested_offset < 0) {
|
|
||||||
/* impossible to seek */
|
|
||||||
GST_DEBUG_OBJECT (typefind,
|
|
||||||
"'%s' was reset - couldn't seek to %" G_GINT64_FORMAT,
|
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory), seek_offset);
|
|
||||||
if (entry->probability == 0) {
|
|
||||||
free_entry (entry);
|
|
||||||
typefind->possibilities =
|
|
||||||
g_list_delete_link (typefind->possibilities, walk);
|
|
||||||
/* FIXME: too many gotos */
|
|
||||||
if (!typefind->possibilities)
|
|
||||||
goto error;
|
|
||||||
/* we modified the list, let's restart */
|
|
||||||
goto restart;
|
|
||||||
} else {
|
|
||||||
entry->requested_size = 0;
|
|
||||||
entry->requested_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* throw out all entries that can't get more data */
|
|
||||||
walk = g_list_next (typefind->possibilities);
|
|
||||||
while (walk) {
|
while (walk) {
|
||||||
GList *cur = walk;
|
|
||||||
|
|
||||||
entry = (TypeFindEntry *) walk->data;
|
|
||||||
walk = g_list_next (walk);
|
|
||||||
if (entry->requested_size == 0) {
|
|
||||||
GST_DEBUG_OBJECT (typefind,
|
|
||||||
"'%s' was removed - higher possibilities available",
|
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
|
||||||
free_entry (entry);
|
|
||||||
typefind->possibilities =
|
|
||||||
g_list_delete_link (typefind->possibilities, cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (g_list_next (typefind->possibilities) == NULL) {
|
|
||||||
entry = (TypeFindEntry *) typefind->possibilities->data;
|
entry = (TypeFindEntry *) typefind->possibilities->data;
|
||||||
if (entry->probability > typefind->min_probability) {
|
if ((!best || entry->probability > best->probability) &&
|
||||||
GST_INFO_OBJECT (typefind,
|
entry->probability >= typefind->min_probability) {
|
||||||
"'%s' is the only typefind left, using it now (probability %u)",
|
best = entry;
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
|
|
||||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
|
||||||
0, entry->probability, entry->caps);
|
|
||||||
free_entry (entry);
|
|
||||||
g_list_free (typefind->possibilities);
|
|
||||||
typefind->possibilities = NULL;
|
|
||||||
stop_typefinding (typefind);
|
|
||||||
}
|
}
|
||||||
|
walk = g_list_next (walk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best) {
|
||||||
|
GST_INFO_OBJECT (typefind,
|
||||||
|
"'%s' is the only typefind left, using it now (probability %u)",
|
||||||
|
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
|
||||||
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||||
|
0, entry->probability, entry->caps);
|
||||||
|
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
|
||||||
|
g_list_free (typefind->possibilities);
|
||||||
|
typefind->possibilities = NULL;
|
||||||
|
stop_typefinding (typefind);
|
||||||
|
} else {
|
||||||
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
||||||
|
stop_typefinding (typefind);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -850,27 +749,31 @@ gst_type_find_element_getrange (GstPad * srcpad,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
do_typefind (GstTypeFindElement * typefind)
|
do_pull_typefind (GstTypeFindElement * typefind)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstPad *peer;
|
GstPad *peer;
|
||||||
|
gboolean res = FALSE;
|
||||||
|
|
||||||
peer = gst_pad_get_peer (typefind->sink);
|
peer = gst_pad_get_peer (typefind->sink);
|
||||||
if (peer) {
|
if (peer) {
|
||||||
gst_pad_peer_set_active (typefind->sink, GST_ACTIVATE_PULL);
|
if (gst_pad_peer_set_active (typefind->sink, GST_ACTIVATE_PULL)) {
|
||||||
|
caps = gst_type_find_helper (peer, 0);
|
||||||
caps = gst_type_find_helper (peer, 0);
|
if (caps) {
|
||||||
gst_pad_set_caps (typefind->src, caps);
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||||
|
0, 100, caps);
|
||||||
if (caps) {
|
typefind->mode = MODE_NORMAL;
|
||||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
res = TRUE;
|
||||||
0, 100, caps);
|
}
|
||||||
|
} else {
|
||||||
|
start_typefinding (typefind);
|
||||||
|
res = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_object_unref (GST_OBJECT (peer));
|
gst_object_unref (GST_OBJECT (peer));
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -906,8 +809,8 @@ gst_type_find_element_change_state (GstElement * element)
|
||||||
transition = GST_STATE_TRANSITION (element);
|
transition = GST_STATE_TRANSITION (element);
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_READY_TO_PAUSED:
|
case GST_STATE_READY_TO_PAUSED:
|
||||||
do_typefind (typefind);
|
if (!do_pull_typefind (typefind))
|
||||||
|
return GST_STATE_FAILURE;
|
||||||
//start_typefinding (typefind);
|
//start_typefinding (typefind);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1748,6 +1748,32 @@ gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_buffer_merge:
|
||||||
|
* @buf1: a first source #GstBuffer to merge.
|
||||||
|
* @buf2: the second source #GstBuffer to merge.
|
||||||
|
*
|
||||||
|
* Create a new buffer that is the concatenation of the two source
|
||||||
|
* buffers, and takes ownership of the original source buffers.
|
||||||
|
*
|
||||||
|
* If the buffers point to contiguous areas of memory, the buffer
|
||||||
|
* is created without copying the data.
|
||||||
|
*
|
||||||
|
* Returns: the new #GstBuffer that's the concatenation of the source buffers.
|
||||||
|
*/
|
||||||
|
GstBuffer *
|
||||||
|
gst_buffer_join (GstBuffer * buf1, GstBuffer * buf2)
|
||||||
|
{
|
||||||
|
GstBuffer *result;
|
||||||
|
|
||||||
|
result = gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
|
||||||
|
gst_buffer_unref (buf1);
|
||||||
|
gst_buffer_unref (buf2);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_buffer_stamp:
|
* gst_buffer_stamp:
|
||||||
* @dest: buffer to stamp
|
* @dest: buffer to stamp
|
||||||
|
|
|
@ -281,6 +281,7 @@ void gst_bin_remove_many (GstBin *bin, GstElement *eleme
|
||||||
|
|
||||||
/* buffer functions */
|
/* buffer functions */
|
||||||
GstBuffer * gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2);
|
GstBuffer * gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2);
|
||||||
|
GstBuffer * gst_buffer_join (GstBuffer * buf1, GstBuffer * buf2);
|
||||||
void gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src);
|
void gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src);
|
||||||
|
|
||||||
/* atomic functions */
|
/* atomic functions */
|
||||||
|
|
|
@ -716,7 +716,9 @@ gst_basesrc_activate (GstPad * pad, GstActivateMode mode)
|
||||||
gst_pad_start_task (pad, (GstTaskFunction) gst_basesrc_loop, pad);
|
gst_pad_start_task (pad, (GstTaskFunction) gst_basesrc_loop, pad);
|
||||||
break;
|
break;
|
||||||
case GST_ACTIVATE_PULL:
|
case GST_ACTIVATE_PULL:
|
||||||
result = TRUE;
|
result = basesrc->seekable;
|
||||||
|
if (!result)
|
||||||
|
gst_basesrc_stop (basesrc);
|
||||||
break;
|
break;
|
||||||
case GST_ACTIVATE_NONE:
|
case GST_ACTIVATE_NONE:
|
||||||
/* step 1, unblock clock sync (if any) */
|
/* step 1, unblock clock sync (if any) */
|
||||||
|
|
|
@ -122,7 +122,6 @@ static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
|
||||||
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
|
static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
|
||||||
static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind);
|
|
||||||
|
|
||||||
static gboolean gst_type_find_element_handle_event (GstPad * pad,
|
static gboolean gst_type_find_element_handle_event (GstPad * pad,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
|
@ -226,11 +225,12 @@ gst_type_find_element_init (GstTypeFindElement * typefind)
|
||||||
gst_pad_use_fixed_caps (typefind->src);
|
gst_pad_use_fixed_caps (typefind->src);
|
||||||
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
||||||
|
|
||||||
|
typefind->mode = MODE_TYPEFIND;
|
||||||
typefind->caps = NULL;
|
typefind->caps = NULL;
|
||||||
typefind->min_probability = 1;
|
typefind->min_probability = 1;
|
||||||
typefind->max_probability = GST_TYPE_FIND_MAXIMUM;
|
typefind->max_probability = GST_TYPE_FIND_MAXIMUM;
|
||||||
|
|
||||||
typefind->store = gst_buffer_store_new ();
|
typefind->store = NULL;
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
gst_type_find_element_dispose (GObject * object)
|
gst_type_find_element_dispose (GObject * object)
|
||||||
|
@ -240,7 +240,7 @@ gst_type_find_element_dispose (GObject * object)
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
|
||||||
if (typefind->store) {
|
if (typefind->store) {
|
||||||
g_object_unref (typefind->store);
|
gst_buffer_unref (typefind->store);
|
||||||
typefind->store = NULL;
|
typefind->store = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,7 @@ gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
|
||||||
/* FIXME: this code assumes that there's no discont in the queue */
|
/* FIXME: this code assumes that there's no discont in the queue */
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
peer_pos -= gst_buffer_store_get_size (typefind->store, 0);
|
peer_pos -= typefind->store->size;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
|
@ -369,10 +369,7 @@ typedef struct
|
||||||
GstTypeFindFactory *factory;
|
GstTypeFindFactory *factory;
|
||||||
gint probability;
|
gint probability;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
gint64 requested_offset;
|
|
||||||
guint requested_size;
|
guint requested_size;
|
||||||
|
|
||||||
GList *buffers;
|
|
||||||
GstTypeFindElement *self;
|
GstTypeFindElement *self;
|
||||||
}
|
}
|
||||||
TypeFindEntry;
|
TypeFindEntry;
|
||||||
|
@ -383,17 +380,8 @@ new_entry (void)
|
||||||
return g_new0 (TypeFindEntry, 1);
|
return g_new0 (TypeFindEntry, 1);
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
free_entry_buffers (TypeFindEntry * entry)
|
|
||||||
{
|
|
||||||
g_list_foreach (entry->buffers, (GFunc) gst_mini_object_unref, NULL);
|
|
||||||
g_list_free (entry->buffers);
|
|
||||||
entry->buffers = NULL;
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
free_entry (TypeFindEntry * entry)
|
free_entry (TypeFindEntry * entry)
|
||||||
{
|
{
|
||||||
free_entry_buffers (entry);
|
|
||||||
|
|
||||||
if (entry->caps)
|
if (entry->caps)
|
||||||
gst_caps_unref (entry->caps);
|
gst_caps_unref (entry->caps);
|
||||||
g_free (entry);
|
g_free (entry);
|
||||||
|
@ -416,8 +404,6 @@ static void
|
||||||
stop_typefinding (GstTypeFindElement * typefind)
|
stop_typefinding (GstTypeFindElement * typefind)
|
||||||
{
|
{
|
||||||
GstElementState state;
|
GstElementState state;
|
||||||
|
|
||||||
/* stop all typefinding and set mode back to normal */
|
|
||||||
gboolean push_cached_buffers;
|
gboolean push_cached_buffers;
|
||||||
|
|
||||||
gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, NULL);
|
gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, NULL);
|
||||||
|
@ -436,35 +422,17 @@ stop_typefinding (GstTypeFindElement * typefind)
|
||||||
}
|
}
|
||||||
//typefind->mode = MODE_TRANSITION;
|
//typefind->mode = MODE_TRANSITION;
|
||||||
|
|
||||||
if (!push_cached_buffers) {
|
if (typefind->store) {
|
||||||
gst_buffer_store_clear (typefind->store);
|
if (!push_cached_buffers) {
|
||||||
} else {
|
gst_buffer_unref (typefind->store);
|
||||||
typefind->mode = MODE_NORMAL;
|
} else {
|
||||||
/* push out our queued buffers here */
|
typefind->mode = MODE_NORMAL;
|
||||||
push_buffer_store (typefind);
|
gst_pad_push (typefind->src, typefind->store);
|
||||||
|
}
|
||||||
|
typefind->store = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
push_buffer_store (GstTypeFindElement * typefind)
|
|
||||||
{
|
|
||||||
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
|
||||||
GstBuffer *buffer;
|
|
||||||
GstFlowReturn ret;
|
|
||||||
|
|
||||||
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
|
||||||
GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
|
|
||||||
ret = gst_pad_push (typefind->src, buffer);
|
|
||||||
} else {
|
|
||||||
size = 0;
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_buffer_store_clear (typefind->store);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint64
|
static guint64
|
||||||
find_element_get_length (gpointer data)
|
find_element_get_length (gpointer data)
|
||||||
{
|
{
|
||||||
|
@ -529,7 +497,8 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
|
||||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||||
0, entry->probability, entry->caps);
|
0, entry->probability, entry->caps);
|
||||||
stop_typefinding (typefind);
|
stop_typefinding (typefind);
|
||||||
push_buffer_store (typefind);
|
gst_pad_push (typefind->src, typefind->store);
|
||||||
|
typefind->store = NULL;
|
||||||
res = gst_pad_event_default (pad, event);
|
res = gst_pad_event_default (pad, event);
|
||||||
} else {
|
} else {
|
||||||
res = gst_pad_event_default (pad, event);
|
res = gst_pad_event_default (pad, event);
|
||||||
|
@ -561,37 +530,21 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
|
||||||
static guint8 *
|
static guint8 *
|
||||||
find_peek (gpointer data, gint64 offset, guint size)
|
find_peek (gpointer data, gint64 offset, guint size)
|
||||||
{
|
{
|
||||||
GstBuffer *buf;
|
|
||||||
TypeFindEntry *entry = (TypeFindEntry *) data;
|
TypeFindEntry *entry = (TypeFindEntry *) data;
|
||||||
|
|
||||||
GST_LOG_OBJECT (entry->self, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
|
GST_LOG_OBJECT (entry->self, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory), offset, size);
|
GST_PLUGIN_FEATURE_NAME (entry->factory), offset, size);
|
||||||
if (offset >= 0) {
|
if (offset != 0)
|
||||||
buf = gst_buffer_store_get_buffer (entry->self->store, offset, size);
|
return NULL;
|
||||||
} else {
|
|
||||||
/* FIXME: can we do this easily without querying length? */
|
|
||||||
guint64 length = find_element_get_length (data);
|
|
||||||
|
|
||||||
if (length < -offset) {
|
if (size <= entry->self->store->size) {
|
||||||
buf = NULL;
|
return GST_BUFFER_DATA (entry->self->store);
|
||||||
} else {
|
|
||||||
buf =
|
|
||||||
gst_buffer_store_get_buffer (entry->self->store, length + offset,
|
|
||||||
size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf) {
|
|
||||||
entry->buffers = g_list_prepend (entry->buffers, buf);
|
|
||||||
return GST_BUFFER_DATA (buf);
|
|
||||||
} else {
|
} else {
|
||||||
if (entry->requested_size == 0) {
|
entry->requested_size = size;
|
||||||
GST_LOG_OBJECT (entry->self,
|
|
||||||
"setting requested peek (%" G_GINT64_FORMAT ", %u) on '%s'", offset,
|
GST_LOG_OBJECT (entry->self,
|
||||||
size, GST_PLUGIN_FEATURE_NAME (entry->factory));
|
"setting requested peek (%" G_GINT64_FORMAT ", %u) on '%s'", offset,
|
||||||
entry->requested_offset = offset;
|
size, GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||||
entry->requested_size = size;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,6 +561,7 @@ find_suggest (gpointer data, guint probability, const GstCaps * caps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static gint
|
static gint
|
||||||
compare_type_find_entry (gconstpointer a, gconstpointer b)
|
compare_type_find_entry (gconstpointer a, gconstpointer b)
|
||||||
{
|
{
|
||||||
|
@ -621,6 +575,7 @@ compare_type_find_entry (gconstpointer a, gconstpointer b)
|
||||||
return two->probability - one->probability;
|
return two->probability - one->probability;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
compare_type_find_factory (gconstpointer fac1, gconstpointer fac2)
|
compare_type_find_factory (gconstpointer fac1, gconstpointer fac2)
|
||||||
|
@ -644,20 +599,19 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
case MODE_NORMAL:
|
case MODE_NORMAL:
|
||||||
return gst_pad_push (typefind->src, buffer);
|
return gst_pad_push (typefind->src, buffer);
|
||||||
case MODE_TYPEFIND:{
|
case MODE_TYPEFIND:{
|
||||||
guint64 current_offset;
|
gboolean done = TRUE;
|
||||||
|
|
||||||
gst_buffer_store_add_buffer (typefind->store, buffer);
|
if (typefind->store)
|
||||||
current_offset = GST_BUFFER_OFFSET_IS_VALID (buffer) ?
|
typefind->store = gst_buffer_join (typefind->store, buffer);
|
||||||
GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) :
|
else
|
||||||
gst_buffer_store_get_size (typefind->store, 0);
|
typefind->store = buffer;
|
||||||
gst_buffer_unref (buffer);
|
|
||||||
|
|
||||||
if (typefind->possibilities == NULL) {
|
if (typefind->possibilities == NULL) {
|
||||||
/* not yet started, get all typefinding functions into our "queue" */
|
/* not yet started, get all typefinding functions into our "queue" */
|
||||||
GList *all_factories = gst_type_find_factory_get_list ();
|
GList *all_factories = gst_type_find_factory_get_list ();
|
||||||
|
|
||||||
GST_INFO_OBJECT (typefind, "starting with %u typefinding functions",
|
GST_INFO_OBJECT (typefind, "starting with %u typefinding functions",
|
||||||
g_list_length ((GList *) all_factories));
|
g_list_length (all_factories));
|
||||||
|
|
||||||
all_factories = g_list_sort (all_factories, compare_type_find_factory);
|
all_factories = g_list_sort (all_factories, compare_type_find_factory);
|
||||||
walk = all_factories;
|
walk = all_factories;
|
||||||
|
@ -673,6 +627,7 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
}
|
}
|
||||||
g_list_free (all_factories);
|
g_list_free (all_factories);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call every typefind function once */
|
/* call every typefind function once */
|
||||||
walk = entries = typefind->possibilities;
|
walk = entries = typefind->possibilities;
|
||||||
GST_INFO_OBJECT (typefind, "iterating %u typefinding functions",
|
GST_INFO_OBJECT (typefind, "iterating %u typefinding functions",
|
||||||
|
@ -681,11 +636,14 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
while (walk) {
|
while (walk) {
|
||||||
find.data = entry = (TypeFindEntry *) walk->data;
|
find.data = entry = (TypeFindEntry *) walk->data;
|
||||||
walk = g_list_next (walk);
|
walk = g_list_next (walk);
|
||||||
entry->probability = 0;
|
if (entry->probability == 0) {
|
||||||
entry->requested_offset = 0;
|
entry->requested_size = 0;
|
||||||
entry->requested_size = 0;
|
gst_type_find_factory_call_function (entry->factory, &find);
|
||||||
gst_type_find_factory_call_function (entry->factory, &find);
|
} else {
|
||||||
free_entry_buffers (entry);
|
typefind->possibilities =
|
||||||
|
g_list_prepend (typefind->possibilities, entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (entry->probability == 0 && entry->requested_size == 0) {
|
if (entry->probability == 0 && entry->requested_size == 0) {
|
||||||
GST_DEBUG_OBJECT (typefind,
|
GST_DEBUG_OBJECT (typefind,
|
||||||
"'%s' was removed - no chance of being the right plugin",
|
"'%s' was removed - no chance of being the right plugin",
|
||||||
|
@ -709,113 +667,54 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
free_entry (walk->data);
|
free_entry (walk->data);
|
||||||
walk = g_list_next (walk);
|
walk = g_list_next (walk);
|
||||||
}
|
}
|
||||||
typefind->possibilities = NULL;
|
|
||||||
g_list_free (typefind->possibilities);
|
g_list_free (typefind->possibilities);
|
||||||
|
typefind->possibilities = NULL;
|
||||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
|
||||||
probability, found_caps);
|
probability, found_caps);
|
||||||
free_entry (entry);
|
free_entry (entry);
|
||||||
} else {
|
} else {
|
||||||
typefind->possibilities =
|
typefind->possibilities =
|
||||||
g_list_prepend (typefind->possibilities, entry);
|
g_list_prepend (typefind->possibilities, entry);
|
||||||
|
if (entry->requested_size != 0)
|
||||||
|
done = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_list_free (entries);
|
g_list_free (entries);
|
||||||
|
|
||||||
/* we may now already have caps or we might be left without functions to try */
|
/* we may now already have caps or we might be left without functions to try */
|
||||||
if (typefind->caps) {
|
if (typefind->caps) {
|
||||||
stop_typefinding (typefind);
|
stop_typefinding (typefind);
|
||||||
} else if (typefind->possibilities == NULL) {
|
} else if (typefind->possibilities == NULL) {
|
||||||
error:
|
|
||||||
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
||||||
stop_typefinding (typefind);
|
stop_typefinding (typefind);
|
||||||
} else {
|
return GST_FLOW_ERROR;
|
||||||
/* set up typefind element for next iteration */
|
} else if (done) {
|
||||||
typefind->possibilities =
|
TypeFindEntry *best = NULL;
|
||||||
g_list_sort (typefind->possibilities, compare_type_find_entry);
|
|
||||||
|
|
||||||
/* look for typefind functions that require data without seeking */
|
walk = typefind->possibilities;
|
||||||
for (walk = typefind->possibilities; walk; walk = g_list_next (walk)) {
|
|
||||||
entry = (TypeFindEntry *) walk->data;
|
|
||||||
if (entry->requested_offset <= current_offset &&
|
|
||||||
entry->requested_offset + entry->requested_size > current_offset)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!walk) {
|
|
||||||
/* find out if we should seek */
|
|
||||||
restart:
|
|
||||||
for (walk = typefind->possibilities; walk; walk = g_list_next (walk)) {
|
|
||||||
entry = (TypeFindEntry *) walk->data;
|
|
||||||
if (entry->requested_size > 0) {
|
|
||||||
/* FIXME: need heuristic to find out if we should seek */
|
|
||||||
gint64 seek_offset;
|
|
||||||
GstEvent *event;
|
|
||||||
|
|
||||||
seek_offset =
|
|
||||||
entry->requested_offset >
|
|
||||||
0 ? entry->
|
|
||||||
requested_offset : find_element_get_length (entry) +
|
|
||||||
entry->requested_offset;
|
|
||||||
seek_offset +=
|
|
||||||
gst_buffer_store_get_size (typefind->store, seek_offset);
|
|
||||||
event =
|
|
||||||
gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET,
|
|
||||||
seek_offset);
|
|
||||||
if (gst_pad_send_event (GST_PAD_PEER (typefind->sink), event)) {
|
|
||||||
/* done seeking */
|
|
||||||
GST_DEBUG_OBJECT (typefind,
|
|
||||||
"'%s' was reset - seeked to %" G_GINT64_FORMAT,
|
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory), seek_offset);
|
|
||||||
break;
|
|
||||||
} else if (entry->requested_offset < 0) {
|
|
||||||
/* impossible to seek */
|
|
||||||
GST_DEBUG_OBJECT (typefind,
|
|
||||||
"'%s' was reset - couldn't seek to %" G_GINT64_FORMAT,
|
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory), seek_offset);
|
|
||||||
if (entry->probability == 0) {
|
|
||||||
free_entry (entry);
|
|
||||||
typefind->possibilities =
|
|
||||||
g_list_delete_link (typefind->possibilities, walk);
|
|
||||||
/* FIXME: too many gotos */
|
|
||||||
if (!typefind->possibilities)
|
|
||||||
goto error;
|
|
||||||
/* we modified the list, let's restart */
|
|
||||||
goto restart;
|
|
||||||
} else {
|
|
||||||
entry->requested_size = 0;
|
|
||||||
entry->requested_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* throw out all entries that can't get more data */
|
|
||||||
walk = g_list_next (typefind->possibilities);
|
|
||||||
while (walk) {
|
while (walk) {
|
||||||
GList *cur = walk;
|
|
||||||
|
|
||||||
entry = (TypeFindEntry *) walk->data;
|
|
||||||
walk = g_list_next (walk);
|
|
||||||
if (entry->requested_size == 0) {
|
|
||||||
GST_DEBUG_OBJECT (typefind,
|
|
||||||
"'%s' was removed - higher possibilities available",
|
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
|
||||||
free_entry (entry);
|
|
||||||
typefind->possibilities =
|
|
||||||
g_list_delete_link (typefind->possibilities, cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (g_list_next (typefind->possibilities) == NULL) {
|
|
||||||
entry = (TypeFindEntry *) typefind->possibilities->data;
|
entry = (TypeFindEntry *) typefind->possibilities->data;
|
||||||
if (entry->probability > typefind->min_probability) {
|
if ((!best || entry->probability > best->probability) &&
|
||||||
GST_INFO_OBJECT (typefind,
|
entry->probability >= typefind->min_probability) {
|
||||||
"'%s' is the only typefind left, using it now (probability %u)",
|
best = entry;
|
||||||
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
|
|
||||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
|
||||||
0, entry->probability, entry->caps);
|
|
||||||
free_entry (entry);
|
|
||||||
g_list_free (typefind->possibilities);
|
|
||||||
typefind->possibilities = NULL;
|
|
||||||
stop_typefinding (typefind);
|
|
||||||
}
|
}
|
||||||
|
walk = g_list_next (walk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best) {
|
||||||
|
GST_INFO_OBJECT (typefind,
|
||||||
|
"'%s' is the only typefind left, using it now (probability %u)",
|
||||||
|
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
|
||||||
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||||
|
0, entry->probability, entry->caps);
|
||||||
|
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
|
||||||
|
g_list_free (typefind->possibilities);
|
||||||
|
typefind->possibilities = NULL;
|
||||||
|
stop_typefinding (typefind);
|
||||||
|
} else {
|
||||||
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
||||||
|
stop_typefinding (typefind);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -850,27 +749,31 @@ gst_type_find_element_getrange (GstPad * srcpad,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
do_typefind (GstTypeFindElement * typefind)
|
do_pull_typefind (GstTypeFindElement * typefind)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstPad *peer;
|
GstPad *peer;
|
||||||
|
gboolean res = FALSE;
|
||||||
|
|
||||||
peer = gst_pad_get_peer (typefind->sink);
|
peer = gst_pad_get_peer (typefind->sink);
|
||||||
if (peer) {
|
if (peer) {
|
||||||
gst_pad_peer_set_active (typefind->sink, GST_ACTIVATE_PULL);
|
if (gst_pad_peer_set_active (typefind->sink, GST_ACTIVATE_PULL)) {
|
||||||
|
caps = gst_type_find_helper (peer, 0);
|
||||||
caps = gst_type_find_helper (peer, 0);
|
if (caps) {
|
||||||
gst_pad_set_caps (typefind->src, caps);
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||||
|
0, 100, caps);
|
||||||
if (caps) {
|
typefind->mode = MODE_NORMAL;
|
||||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
res = TRUE;
|
||||||
0, 100, caps);
|
}
|
||||||
|
} else {
|
||||||
|
start_typefinding (typefind);
|
||||||
|
res = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_object_unref (GST_OBJECT (peer));
|
gst_object_unref (GST_OBJECT (peer));
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -906,8 +809,8 @@ gst_type_find_element_change_state (GstElement * element)
|
||||||
transition = GST_STATE_TRANSITION (element);
|
transition = GST_STATE_TRANSITION (element);
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_READY_TO_PAUSED:
|
case GST_STATE_READY_TO_PAUSED:
|
||||||
do_typefind (typefind);
|
if (!do_pull_typefind (typefind))
|
||||||
|
return GST_STATE_FAILURE;
|
||||||
//start_typefinding (typefind);
|
//start_typefinding (typefind);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue