mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-25 21:40:34 +00:00
loads of fixes. Most of the stuff works now (only thing missing is vorbis streams)
Original commit message from CVS: loads of fixes. Most of the stuff works now (only thing missing is vorbis streams)
This commit is contained in:
parent
59c9a1133d
commit
c2842aedf8
8 changed files with 299 additions and 102 deletions
|
@ -430,7 +430,8 @@ spider_find_peek (gpointer data, gint64 offset, guint size)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void spider_find_suggest (gpointer data, guint probability, GstCaps *caps)
|
static void
|
||||||
|
spider_find_suggest (gpointer data, guint probability, GstCaps *caps)
|
||||||
{
|
{
|
||||||
SpiderTypeFind *find = (SpiderTypeFind *) data;
|
SpiderTypeFind *find = (SpiderTypeFind *) data;
|
||||||
G_GNUC_UNUSED gchar *caps_str;
|
G_GNUC_UNUSED gchar *caps_str;
|
||||||
|
@ -459,6 +460,7 @@ gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
|
||||||
data = gst_pad_pull (ident->sink);
|
data = gst_pad_pull (ident->sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
find.buffer = GST_BUFFER (data);
|
||||||
/* maybe there are already valid caps now? */
|
/* maybe there are already valid caps now? */
|
||||||
if ((find.caps = gst_pad_get_caps (ident->sink)) != NULL) {
|
if ((find.caps = gst_pad_get_caps (ident->sink)) != NULL) {
|
||||||
gst_caps_ref (find.caps); /* it's unrefed later below */
|
gst_caps_ref (find.caps); /* it's unrefed later below */
|
||||||
|
@ -468,7 +470,6 @@ gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
|
||||||
/* now do the actual typefinding with the supplied buffer */
|
/* now do the actual typefinding with the supplied buffer */
|
||||||
type_list = gst_type_find_factory_get_list ();
|
type_list = gst_type_find_factory_get_list ();
|
||||||
|
|
||||||
find.buffer = GST_BUFFER (data);
|
|
||||||
find.best_probability = 0;
|
find.best_probability = 0;
|
||||||
find.caps = NULL;
|
find.caps = NULL;
|
||||||
gst_find.data = &find;
|
gst_find.data = &find;
|
||||||
|
|
|
@ -143,7 +143,7 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
||||||
GST_LOG_OBJECT (store, "adding buffer %p with invalid offset and size %u",
|
GST_LOG_OBJECT (store, "adding buffer %p with invalid offset and size %u",
|
||||||
buffer, GST_BUFFER_SIZE (buffer));
|
buffer, GST_BUFFER_SIZE (buffer));
|
||||||
gst_data_ref (GST_DATA (buffer));
|
gst_data_ref (GST_DATA (buffer));
|
||||||
g_list_append (store->buffers, buffer);
|
store->buffers = g_list_append (store->buffers, buffer);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else {
|
} else {
|
||||||
/* both list and buffer have valid offsets, we can really go wild */
|
/* both list and buffer have valid offsets, we can really go wild */
|
||||||
|
@ -326,6 +326,8 @@ gst_buffer_store_get_buffer (GstBufferStore *store, guint64 offset, guint size)
|
||||||
current, offset, size);
|
current, offset, size);
|
||||||
ret = current;
|
ret = current;
|
||||||
gst_data_ref (GST_DATA (ret));
|
gst_data_ref (GST_DATA (ret));
|
||||||
|
GST_LOG_OBJECT (store, "refcount %d",
|
||||||
|
GST_DATA_REFCOUNT_VALUE(ret));
|
||||||
break;
|
break;
|
||||||
} else if (cur_offset + GST_BUFFER_SIZE (current) > offset) {
|
} else if (cur_offset + GST_BUFFER_SIZE (current) > offset) {
|
||||||
if (cur_offset + GST_BUFFER_SIZE (current) >= offset + size) {
|
if (cur_offset + GST_BUFFER_SIZE (current) >= offset + size) {
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* FIXME: need a better solution for non-seekable streams */
|
||||||
|
|
||||||
/* way of operation:
|
/* way of operation:
|
||||||
* 1) get a list of all typefind functions sorted best to worst
|
* 1) get a list of all typefind functions sorted best to worst
|
||||||
* 2) if all elements have been called with all requested data goto 8
|
* 2) if all elements have been called with all requested data goto 8
|
||||||
|
@ -99,6 +101,11 @@ static void gst_type_find_element_get_property (GObject * object,
|
||||||
GValue * value,
|
GValue * value,
|
||||||
GParamSpec * pspec);
|
GParamSpec * pspec);
|
||||||
|
|
||||||
|
static const GstEventMask *
|
||||||
|
gst_type_find_element_src_event_mask (GstPad * pad);
|
||||||
|
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
||||||
|
GstEvent * event);
|
||||||
|
|
||||||
static void gst_type_find_element_chain (GstPad * sinkpad,
|
static void gst_type_find_element_chain (GstPad * sinkpad,
|
||||||
GstData * data);
|
GstData * data);
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
|
@ -197,6 +204,8 @@ gst_type_find_element_init (GTypeInstance *instance, gpointer g_class)
|
||||||
/* srcpad */
|
/* srcpad */
|
||||||
typefind->src = gst_pad_new_from_template (
|
typefind->src = gst_pad_new_from_template (
|
||||||
GST_PAD_TEMPLATE_GET (type_find_element_src_factory), "src");
|
GST_PAD_TEMPLATE_GET (type_find_element_src_factory), "src");
|
||||||
|
gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event);
|
||||||
|
gst_pad_set_event_mask_function (typefind->src, gst_type_find_element_src_event_mask);
|
||||||
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
||||||
|
|
||||||
typefind->caps = NULL;
|
typefind->caps = NULL;
|
||||||
|
@ -268,6 +277,29 @@ gst_type_find_element_get_property (GObject *object, guint prop_id,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static const GstEventMask *
|
||||||
|
gst_type_find_element_src_event_mask (GstPad *pad)
|
||||||
|
{
|
||||||
|
static const GstEventMask mask[] = {
|
||||||
|
{ GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH},
|
||||||
|
/* add more if you want, event masks suck and need to die anyway */
|
||||||
|
{ 0, }
|
||||||
|
};
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
static gboolean
|
||||||
|
gst_type_find_element_src_event (GstPad *pad, GstEvent *event)
|
||||||
|
{
|
||||||
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
if (typefind->mode == MODE_TYPEFIND) {
|
||||||
|
/* need to do more? */
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return gst_pad_event_default (pad, event);
|
||||||
|
}
|
||||||
static void
|
static void
|
||||||
start_typefinding (GstTypeFindElement *typefind)
|
start_typefinding (GstTypeFindElement *typefind)
|
||||||
{
|
{
|
||||||
|
@ -279,32 +311,14 @@ start_typefinding (GstTypeFindElement *typefind)
|
||||||
typefind->stream_length = 0;
|
typefind->stream_length = 0;
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
stop_typefinding (GstTypeFindElement *typefind)
|
|
||||||
{
|
|
||||||
/* stop all typefinding and set mode back to normal */
|
|
||||||
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
|
||||||
|
|
||||||
g_assert (typefind->possibilities == NULL);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
|
||||||
typefind->mode = MODE_NORMAL;
|
|
||||||
|
|
||||||
if (push_cached_buffers) {
|
|
||||||
GstBuffer *buffer;
|
|
||||||
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
|
||||||
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
|
||||||
gst_pad_push (typefind->src, GST_DATA (buffer));
|
|
||||||
} else {
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
|
||||||
gst_event_new_seek (GST_SEEK_METHOD_SET, size));
|
|
||||||
}
|
|
||||||
gst_buffer_store_clear (typefind->store);
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
||||||
{
|
{
|
||||||
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
if (typefind->mode == MODE_TYPEFIND) {
|
||||||
|
/* need to do more? */
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
}
|
||||||
gst_pad_event_default (pad, event);
|
gst_pad_event_default (pad, event);
|
||||||
}
|
}
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -333,6 +347,40 @@ free_entry (TypeFindEntry *entry)
|
||||||
gst_caps_unref (entry->caps);
|
gst_caps_unref (entry->caps);
|
||||||
g_free (entry);
|
g_free (entry);
|
||||||
}
|
}
|
||||||
|
static void
|
||||||
|
stop_typefinding (GstTypeFindElement *typefind)
|
||||||
|
{
|
||||||
|
/* stop all typefinding and set mode back to normal */
|
||||||
|
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
||||||
|
if (typefind->possibilities != NULL) {
|
||||||
|
/* this can only happen on PAUSED => READY */
|
||||||
|
GST_LOG_OBJECT (typefind, "freeing remaining %u typefind functions", g_list_length (typefind->possibilities));
|
||||||
|
g_assert (push_cached_buffers == FALSE);
|
||||||
|
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
|
||||||
|
g_list_free (typefind->possibilities);
|
||||||
|
typefind->possibilities = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
typefind->mode = MODE_NORMAL;
|
||||||
|
|
||||||
|
if (push_cached_buffers) {
|
||||||
|
GstBuffer *buffer;
|
||||||
|
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
||||||
|
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
||||||
|
gst_pad_push (typefind->src, GST_DATA (buffer));
|
||||||
|
} else {
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
GST_LOG_OBJECT (typefind, "seeking back to current position %u", size);
|
||||||
|
if (!gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
||||||
|
gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES, size))) {
|
||||||
|
GST_WARNING_OBJECT (typefind, "could not seek to required position %u, hope for the best", size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gst_buffer_store_clear (typefind->store);
|
||||||
|
}
|
||||||
static guint64
|
static guint64
|
||||||
find_element_get_length (gpointer data)
|
find_element_get_length (gpointer data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* FIXME: need a better solution for non-seekable streams */
|
||||||
|
|
||||||
/* way of operation:
|
/* way of operation:
|
||||||
* 1) get a list of all typefind functions sorted best to worst
|
* 1) get a list of all typefind functions sorted best to worst
|
||||||
* 2) if all elements have been called with all requested data goto 8
|
* 2) if all elements have been called with all requested data goto 8
|
||||||
|
@ -99,6 +101,11 @@ static void gst_type_find_element_get_property (GObject * object,
|
||||||
GValue * value,
|
GValue * value,
|
||||||
GParamSpec * pspec);
|
GParamSpec * pspec);
|
||||||
|
|
||||||
|
static const GstEventMask *
|
||||||
|
gst_type_find_element_src_event_mask (GstPad * pad);
|
||||||
|
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
||||||
|
GstEvent * event);
|
||||||
|
|
||||||
static void gst_type_find_element_chain (GstPad * sinkpad,
|
static void gst_type_find_element_chain (GstPad * sinkpad,
|
||||||
GstData * data);
|
GstData * data);
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
|
@ -197,6 +204,8 @@ gst_type_find_element_init (GTypeInstance *instance, gpointer g_class)
|
||||||
/* srcpad */
|
/* srcpad */
|
||||||
typefind->src = gst_pad_new_from_template (
|
typefind->src = gst_pad_new_from_template (
|
||||||
GST_PAD_TEMPLATE_GET (type_find_element_src_factory), "src");
|
GST_PAD_TEMPLATE_GET (type_find_element_src_factory), "src");
|
||||||
|
gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event);
|
||||||
|
gst_pad_set_event_mask_function (typefind->src, gst_type_find_element_src_event_mask);
|
||||||
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
||||||
|
|
||||||
typefind->caps = NULL;
|
typefind->caps = NULL;
|
||||||
|
@ -268,6 +277,29 @@ gst_type_find_element_get_property (GObject *object, guint prop_id,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static const GstEventMask *
|
||||||
|
gst_type_find_element_src_event_mask (GstPad *pad)
|
||||||
|
{
|
||||||
|
static const GstEventMask mask[] = {
|
||||||
|
{ GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH},
|
||||||
|
/* add more if you want, event masks suck and need to die anyway */
|
||||||
|
{ 0, }
|
||||||
|
};
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
static gboolean
|
||||||
|
gst_type_find_element_src_event (GstPad *pad, GstEvent *event)
|
||||||
|
{
|
||||||
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
if (typefind->mode == MODE_TYPEFIND) {
|
||||||
|
/* need to do more? */
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return gst_pad_event_default (pad, event);
|
||||||
|
}
|
||||||
static void
|
static void
|
||||||
start_typefinding (GstTypeFindElement *typefind)
|
start_typefinding (GstTypeFindElement *typefind)
|
||||||
{
|
{
|
||||||
|
@ -279,32 +311,14 @@ start_typefinding (GstTypeFindElement *typefind)
|
||||||
typefind->stream_length = 0;
|
typefind->stream_length = 0;
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
stop_typefinding (GstTypeFindElement *typefind)
|
|
||||||
{
|
|
||||||
/* stop all typefinding and set mode back to normal */
|
|
||||||
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
|
||||||
|
|
||||||
g_assert (typefind->possibilities == NULL);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
|
||||||
typefind->mode = MODE_NORMAL;
|
|
||||||
|
|
||||||
if (push_cached_buffers) {
|
|
||||||
GstBuffer *buffer;
|
|
||||||
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
|
||||||
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
|
||||||
gst_pad_push (typefind->src, GST_DATA (buffer));
|
|
||||||
} else {
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
|
||||||
gst_event_new_seek (GST_SEEK_METHOD_SET, size));
|
|
||||||
}
|
|
||||||
gst_buffer_store_clear (typefind->store);
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
||||||
{
|
{
|
||||||
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
if (typefind->mode == MODE_TYPEFIND) {
|
||||||
|
/* need to do more? */
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
}
|
||||||
gst_pad_event_default (pad, event);
|
gst_pad_event_default (pad, event);
|
||||||
}
|
}
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -333,6 +347,40 @@ free_entry (TypeFindEntry *entry)
|
||||||
gst_caps_unref (entry->caps);
|
gst_caps_unref (entry->caps);
|
||||||
g_free (entry);
|
g_free (entry);
|
||||||
}
|
}
|
||||||
|
static void
|
||||||
|
stop_typefinding (GstTypeFindElement *typefind)
|
||||||
|
{
|
||||||
|
/* stop all typefinding and set mode back to normal */
|
||||||
|
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
||||||
|
if (typefind->possibilities != NULL) {
|
||||||
|
/* this can only happen on PAUSED => READY */
|
||||||
|
GST_LOG_OBJECT (typefind, "freeing remaining %u typefind functions", g_list_length (typefind->possibilities));
|
||||||
|
g_assert (push_cached_buffers == FALSE);
|
||||||
|
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
|
||||||
|
g_list_free (typefind->possibilities);
|
||||||
|
typefind->possibilities = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
typefind->mode = MODE_NORMAL;
|
||||||
|
|
||||||
|
if (push_cached_buffers) {
|
||||||
|
GstBuffer *buffer;
|
||||||
|
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
||||||
|
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
||||||
|
gst_pad_push (typefind->src, GST_DATA (buffer));
|
||||||
|
} else {
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
GST_LOG_OBJECT (typefind, "seeking back to current position %u", size);
|
||||||
|
if (!gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
||||||
|
gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES, size))) {
|
||||||
|
GST_WARNING_OBJECT (typefind, "could not seek to required position %u, hope for the best", size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gst_buffer_store_clear (typefind->store);
|
||||||
|
}
|
||||||
static guint64
|
static guint64
|
||||||
find_element_get_length (gpointer data)
|
find_element_get_length (gpointer data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,8 +78,6 @@ gst_bytestream_new (GstPad * pad)
|
||||||
{
|
{
|
||||||
GstByteStream *bs = g_new (GstByteStream, 1);
|
GstByteStream *bs = g_new (GstByteStream, 1);
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (debug_bs, "bytestream", 0, "bytestream library");
|
|
||||||
|
|
||||||
bs->pad = pad;
|
bs->pad = pad;
|
||||||
gst_bytestream_init (bs);
|
gst_bytestream_init (bs);
|
||||||
|
|
||||||
|
@ -750,6 +748,8 @@ gst_bytestream_print_status (GstByteStream * bs)
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_init (GModule *module, GstPlugin *plugin)
|
plugin_init (GModule *module, GstPlugin *plugin)
|
||||||
{
|
{
|
||||||
|
GST_DEBUG_CATEGORY_INIT (debug_bs, "bytestream", 0, "bytestream library");
|
||||||
|
|
||||||
gst_plugin_set_longname (plugin, "GstByteStream: a byte-oriented layer on top of buffer-passing");
|
gst_plugin_set_longname (plugin, "GstByteStream: a byte-oriented layer on top of buffer-passing");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
||||||
GST_LOG_OBJECT (store, "adding buffer %p with invalid offset and size %u",
|
GST_LOG_OBJECT (store, "adding buffer %p with invalid offset and size %u",
|
||||||
buffer, GST_BUFFER_SIZE (buffer));
|
buffer, GST_BUFFER_SIZE (buffer));
|
||||||
gst_data_ref (GST_DATA (buffer));
|
gst_data_ref (GST_DATA (buffer));
|
||||||
g_list_append (store->buffers, buffer);
|
store->buffers = g_list_append (store->buffers, buffer);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else {
|
} else {
|
||||||
/* both list and buffer have valid offsets, we can really go wild */
|
/* both list and buffer have valid offsets, we can really go wild */
|
||||||
|
@ -326,6 +326,8 @@ gst_buffer_store_get_buffer (GstBufferStore *store, guint64 offset, guint size)
|
||||||
current, offset, size);
|
current, offset, size);
|
||||||
ret = current;
|
ret = current;
|
||||||
gst_data_ref (GST_DATA (ret));
|
gst_data_ref (GST_DATA (ret));
|
||||||
|
GST_LOG_OBJECT (store, "refcount %d",
|
||||||
|
GST_DATA_REFCOUNT_VALUE(ret));
|
||||||
break;
|
break;
|
||||||
} else if (cur_offset + GST_BUFFER_SIZE (current) > offset) {
|
} else if (cur_offset + GST_BUFFER_SIZE (current) > offset) {
|
||||||
if (cur_offset + GST_BUFFER_SIZE (current) >= offset + size) {
|
if (cur_offset + GST_BUFFER_SIZE (current) >= offset + size) {
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* FIXME: need a better solution for non-seekable streams */
|
||||||
|
|
||||||
/* way of operation:
|
/* way of operation:
|
||||||
* 1) get a list of all typefind functions sorted best to worst
|
* 1) get a list of all typefind functions sorted best to worst
|
||||||
* 2) if all elements have been called with all requested data goto 8
|
* 2) if all elements have been called with all requested data goto 8
|
||||||
|
@ -99,6 +101,11 @@ static void gst_type_find_element_get_property (GObject * object,
|
||||||
GValue * value,
|
GValue * value,
|
||||||
GParamSpec * pspec);
|
GParamSpec * pspec);
|
||||||
|
|
||||||
|
static const GstEventMask *
|
||||||
|
gst_type_find_element_src_event_mask (GstPad * pad);
|
||||||
|
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
||||||
|
GstEvent * event);
|
||||||
|
|
||||||
static void gst_type_find_element_chain (GstPad * sinkpad,
|
static void gst_type_find_element_chain (GstPad * sinkpad,
|
||||||
GstData * data);
|
GstData * data);
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
|
@ -197,6 +204,8 @@ gst_type_find_element_init (GTypeInstance *instance, gpointer g_class)
|
||||||
/* srcpad */
|
/* srcpad */
|
||||||
typefind->src = gst_pad_new_from_template (
|
typefind->src = gst_pad_new_from_template (
|
||||||
GST_PAD_TEMPLATE_GET (type_find_element_src_factory), "src");
|
GST_PAD_TEMPLATE_GET (type_find_element_src_factory), "src");
|
||||||
|
gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event);
|
||||||
|
gst_pad_set_event_mask_function (typefind->src, gst_type_find_element_src_event_mask);
|
||||||
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
||||||
|
|
||||||
typefind->caps = NULL;
|
typefind->caps = NULL;
|
||||||
|
@ -268,6 +277,29 @@ gst_type_find_element_get_property (GObject *object, guint prop_id,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static const GstEventMask *
|
||||||
|
gst_type_find_element_src_event_mask (GstPad *pad)
|
||||||
|
{
|
||||||
|
static const GstEventMask mask[] = {
|
||||||
|
{ GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH},
|
||||||
|
/* add more if you want, event masks suck and need to die anyway */
|
||||||
|
{ 0, }
|
||||||
|
};
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
static gboolean
|
||||||
|
gst_type_find_element_src_event (GstPad *pad, GstEvent *event)
|
||||||
|
{
|
||||||
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
if (typefind->mode == MODE_TYPEFIND) {
|
||||||
|
/* need to do more? */
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return gst_pad_event_default (pad, event);
|
||||||
|
}
|
||||||
static void
|
static void
|
||||||
start_typefinding (GstTypeFindElement *typefind)
|
start_typefinding (GstTypeFindElement *typefind)
|
||||||
{
|
{
|
||||||
|
@ -279,32 +311,14 @@ start_typefinding (GstTypeFindElement *typefind)
|
||||||
typefind->stream_length = 0;
|
typefind->stream_length = 0;
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
stop_typefinding (GstTypeFindElement *typefind)
|
|
||||||
{
|
|
||||||
/* stop all typefinding and set mode back to normal */
|
|
||||||
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
|
||||||
|
|
||||||
g_assert (typefind->possibilities == NULL);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
|
||||||
typefind->mode = MODE_NORMAL;
|
|
||||||
|
|
||||||
if (push_cached_buffers) {
|
|
||||||
GstBuffer *buffer;
|
|
||||||
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
|
||||||
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
|
||||||
gst_pad_push (typefind->src, GST_DATA (buffer));
|
|
||||||
} else {
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
|
||||||
gst_event_new_seek (GST_SEEK_METHOD_SET, size));
|
|
||||||
}
|
|
||||||
gst_buffer_store_clear (typefind->store);
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
||||||
{
|
{
|
||||||
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
if (typefind->mode == MODE_TYPEFIND) {
|
||||||
|
/* need to do more? */
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
}
|
||||||
gst_pad_event_default (pad, event);
|
gst_pad_event_default (pad, event);
|
||||||
}
|
}
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -333,6 +347,40 @@ free_entry (TypeFindEntry *entry)
|
||||||
gst_caps_unref (entry->caps);
|
gst_caps_unref (entry->caps);
|
||||||
g_free (entry);
|
g_free (entry);
|
||||||
}
|
}
|
||||||
|
static void
|
||||||
|
stop_typefinding (GstTypeFindElement *typefind)
|
||||||
|
{
|
||||||
|
/* stop all typefinding and set mode back to normal */
|
||||||
|
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
||||||
|
if (typefind->possibilities != NULL) {
|
||||||
|
/* this can only happen on PAUSED => READY */
|
||||||
|
GST_LOG_OBJECT (typefind, "freeing remaining %u typefind functions", g_list_length (typefind->possibilities));
|
||||||
|
g_assert (push_cached_buffers == FALSE);
|
||||||
|
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
|
||||||
|
g_list_free (typefind->possibilities);
|
||||||
|
typefind->possibilities = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
typefind->mode = MODE_NORMAL;
|
||||||
|
|
||||||
|
if (push_cached_buffers) {
|
||||||
|
GstBuffer *buffer;
|
||||||
|
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
||||||
|
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
||||||
|
gst_pad_push (typefind->src, GST_DATA (buffer));
|
||||||
|
} else {
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
GST_LOG_OBJECT (typefind, "seeking back to current position %u", size);
|
||||||
|
if (!gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
||||||
|
gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES, size))) {
|
||||||
|
GST_WARNING_OBJECT (typefind, "could not seek to required position %u, hope for the best", size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gst_buffer_store_clear (typefind->store);
|
||||||
|
}
|
||||||
static guint64
|
static guint64
|
||||||
find_element_get_length (gpointer data)
|
find_element_get_length (gpointer data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* FIXME: need a better solution for non-seekable streams */
|
||||||
|
|
||||||
/* way of operation:
|
/* way of operation:
|
||||||
* 1) get a list of all typefind functions sorted best to worst
|
* 1) get a list of all typefind functions sorted best to worst
|
||||||
* 2) if all elements have been called with all requested data goto 8
|
* 2) if all elements have been called with all requested data goto 8
|
||||||
|
@ -99,6 +101,11 @@ static void gst_type_find_element_get_property (GObject * object,
|
||||||
GValue * value,
|
GValue * value,
|
||||||
GParamSpec * pspec);
|
GParamSpec * pspec);
|
||||||
|
|
||||||
|
static const GstEventMask *
|
||||||
|
gst_type_find_element_src_event_mask (GstPad * pad);
|
||||||
|
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
||||||
|
GstEvent * event);
|
||||||
|
|
||||||
static void gst_type_find_element_chain (GstPad * sinkpad,
|
static void gst_type_find_element_chain (GstPad * sinkpad,
|
||||||
GstData * data);
|
GstData * data);
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
|
@ -197,6 +204,8 @@ gst_type_find_element_init (GTypeInstance *instance, gpointer g_class)
|
||||||
/* srcpad */
|
/* srcpad */
|
||||||
typefind->src = gst_pad_new_from_template (
|
typefind->src = gst_pad_new_from_template (
|
||||||
GST_PAD_TEMPLATE_GET (type_find_element_src_factory), "src");
|
GST_PAD_TEMPLATE_GET (type_find_element_src_factory), "src");
|
||||||
|
gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event);
|
||||||
|
gst_pad_set_event_mask_function (typefind->src, gst_type_find_element_src_event_mask);
|
||||||
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
||||||
|
|
||||||
typefind->caps = NULL;
|
typefind->caps = NULL;
|
||||||
|
@ -268,6 +277,29 @@ gst_type_find_element_get_property (GObject *object, guint prop_id,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static const GstEventMask *
|
||||||
|
gst_type_find_element_src_event_mask (GstPad *pad)
|
||||||
|
{
|
||||||
|
static const GstEventMask mask[] = {
|
||||||
|
{ GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH},
|
||||||
|
/* add more if you want, event masks suck and need to die anyway */
|
||||||
|
{ 0, }
|
||||||
|
};
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
static gboolean
|
||||||
|
gst_type_find_element_src_event (GstPad *pad, GstEvent *event)
|
||||||
|
{
|
||||||
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
if (typefind->mode == MODE_TYPEFIND) {
|
||||||
|
/* need to do more? */
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return gst_pad_event_default (pad, event);
|
||||||
|
}
|
||||||
static void
|
static void
|
||||||
start_typefinding (GstTypeFindElement *typefind)
|
start_typefinding (GstTypeFindElement *typefind)
|
||||||
{
|
{
|
||||||
|
@ -279,32 +311,14 @@ start_typefinding (GstTypeFindElement *typefind)
|
||||||
typefind->stream_length = 0;
|
typefind->stream_length = 0;
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
stop_typefinding (GstTypeFindElement *typefind)
|
|
||||||
{
|
|
||||||
/* stop all typefinding and set mode back to normal */
|
|
||||||
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
|
||||||
|
|
||||||
g_assert (typefind->possibilities == NULL);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
|
||||||
typefind->mode = MODE_NORMAL;
|
|
||||||
|
|
||||||
if (push_cached_buffers) {
|
|
||||||
GstBuffer *buffer;
|
|
||||||
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
|
||||||
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
|
||||||
gst_pad_push (typefind->src, GST_DATA (buffer));
|
|
||||||
} else {
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
|
||||||
gst_event_new_seek (GST_SEEK_METHOD_SET, size));
|
|
||||||
}
|
|
||||||
gst_buffer_store_clear (typefind->store);
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
||||||
{
|
{
|
||||||
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
if (typefind->mode == MODE_TYPEFIND) {
|
||||||
|
/* need to do more? */
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
}
|
||||||
gst_pad_event_default (pad, event);
|
gst_pad_event_default (pad, event);
|
||||||
}
|
}
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -333,6 +347,40 @@ free_entry (TypeFindEntry *entry)
|
||||||
gst_caps_unref (entry->caps);
|
gst_caps_unref (entry->caps);
|
||||||
g_free (entry);
|
g_free (entry);
|
||||||
}
|
}
|
||||||
|
static void
|
||||||
|
stop_typefinding (GstTypeFindElement *typefind)
|
||||||
|
{
|
||||||
|
/* stop all typefinding and set mode back to normal */
|
||||||
|
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
||||||
|
if (typefind->possibilities != NULL) {
|
||||||
|
/* this can only happen on PAUSED => READY */
|
||||||
|
GST_LOG_OBJECT (typefind, "freeing remaining %u typefind functions", g_list_length (typefind->possibilities));
|
||||||
|
g_assert (push_cached_buffers == FALSE);
|
||||||
|
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
|
||||||
|
g_list_free (typefind->possibilities);
|
||||||
|
typefind->possibilities = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
typefind->mode = MODE_NORMAL;
|
||||||
|
|
||||||
|
if (push_cached_buffers) {
|
||||||
|
GstBuffer *buffer;
|
||||||
|
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
||||||
|
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
||||||
|
gst_pad_push (typefind->src, GST_DATA (buffer));
|
||||||
|
} else {
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
GST_LOG_OBJECT (typefind, "seeking back to current position %u", size);
|
||||||
|
if (!gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
||||||
|
gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES, size))) {
|
||||||
|
GST_WARNING_OBJECT (typefind, "could not seek to required position %u, hope for the best", size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gst_buffer_store_clear (typefind->store);
|
||||||
|
}
|
||||||
static guint64
|
static guint64
|
||||||
find_element_get_length (gpointer data)
|
find_element_get_length (gpointer data)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue