mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-18 05:16:05 +00:00
tagdemux: accumulate buffers in adapter
Accumulate buffers in an adapter instead of appending them because append causes a lot of memcpys. Keep track of the last tagsize and accumulate enough data before attempting to parse more data. This patch implements a minimal amount of changes in order to not change the behaviour. We should really rewrite the tag handling and trimming using the adapter API instead of merging and trimming into a buffer.
This commit is contained in:
parent
2b9118f58c
commit
b55de48843
1 changed files with 61 additions and 18 deletions
|
@ -75,6 +75,7 @@
|
|||
#include "gsttagdemux.h"
|
||||
|
||||
#include <gst/base/gsttypefindhelper.h>
|
||||
#include <gst/base/gstadapter.h>
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -101,8 +102,10 @@ struct _GstTagDemuxPrivate
|
|||
gint64 upstream_size;
|
||||
|
||||
GstTagDemuxState state;
|
||||
GstAdapter *adapter;
|
||||
GstBuffer *collect;
|
||||
gsize collect_size;
|
||||
guint tagsize;
|
||||
GstCaps *src_caps;
|
||||
|
||||
GstTagList *event_tags;
|
||||
|
@ -266,6 +269,8 @@ gst_tag_demux_reset (GstTagDemux * tagdemux)
|
|||
|
||||
gst_buffer_replace (buffer_p, NULL);
|
||||
tagdemux->priv->collect_size = 0;
|
||||
tagdemux->priv->tagsize = 0;
|
||||
gst_adapter_clear (tagdemux->priv->adapter);
|
||||
gst_caps_replace (caps_p, NULL);
|
||||
|
||||
if (tagdemux->priv->event_tags) {
|
||||
|
@ -328,6 +333,7 @@ gst_tag_demux_init (GstTagDemux * demux, GstTagDemuxClass * gclass)
|
|||
gst_pad_use_fixed_caps (demux->priv->srcpad);
|
||||
gst_element_add_pad (GST_ELEMENT (demux), demux->priv->srcpad);
|
||||
|
||||
demux->priv->adapter = gst_adapter_new ();
|
||||
gst_tag_demux_reset (demux);
|
||||
}
|
||||
|
||||
|
@ -337,6 +343,10 @@ gst_tag_demux_dispose (GObject * object)
|
|||
GstTagDemux *tagdemux = GST_TAG_DEMUX (object);
|
||||
|
||||
gst_tag_demux_reset (tagdemux);
|
||||
if (tagdemux->priv->adapter) {
|
||||
g_object_unref (tagdemux->priv->adapter);
|
||||
tagdemux->priv->adapter = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
@ -487,17 +497,58 @@ no_out_buffer_start:
|
|||
}
|
||||
|
||||
static void
|
||||
gst_tag_demux_chain_parse_tag (GstTagDemux * demux, GstBuffer * collect)
|
||||
update_collected (GstTagDemux * demux)
|
||||
{
|
||||
guint avail;
|
||||
GstBuffer *buf;
|
||||
|
||||
avail = gst_adapter_available (demux->priv->adapter);
|
||||
if (avail == 0)
|
||||
return;
|
||||
|
||||
buf = gst_adapter_take_buffer (demux->priv->adapter, avail);
|
||||
|
||||
if (demux->priv->collect == NULL) {
|
||||
demux->priv->collect = buf;
|
||||
} else {
|
||||
demux->priv->collect = gst_buffer_append (demux->priv->collect, buf);
|
||||
}
|
||||
demux->priv->collect_size += avail;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tag_demux_chain_parse_tag (GstTagDemux * demux)
|
||||
{
|
||||
GstBuffer *collect;
|
||||
GstTagDemuxResult parse_ret;
|
||||
GstTagDemuxClass *klass;
|
||||
guint tagsize = 0;
|
||||
guint available;
|
||||
|
||||
g_assert (gst_buffer_is_writable (collect));
|
||||
available =
|
||||
demux->priv->collect_size + gst_adapter_available (demux->priv->adapter);
|
||||
|
||||
klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux));
|
||||
|
||||
if (available < klass->min_start_size) {
|
||||
GST_DEBUG_OBJECT (demux, "Only %u bytes available, but %u needed "
|
||||
"to identify tag", available, klass->min_start_size);
|
||||
return; /* wait for more data */
|
||||
}
|
||||
|
||||
if (available < demux->priv->tagsize) {
|
||||
GST_DEBUG_OBJECT (demux, "Only %u bytes available, but %u needed "
|
||||
"to parse tag", available, demux->priv->tagsize);
|
||||
return; /* wait for more data */
|
||||
}
|
||||
|
||||
update_collected (demux);
|
||||
demux->priv->collect = gst_buffer_make_writable (demux->priv->collect);
|
||||
collect = demux->priv->collect;
|
||||
|
||||
g_assert (gst_buffer_is_writable (collect));
|
||||
|
||||
|
||||
/* If we receive a buffer that's from the middle of the file,
|
||||
* we can't read tags so move to typefinding */
|
||||
if (GST_BUFFER_OFFSET_IS_VALID (collect) && GST_BUFFER_OFFSET (collect) != 0) {
|
||||
|
@ -510,20 +561,14 @@ gst_tag_demux_chain_parse_tag (GstTagDemux * demux, GstBuffer * collect)
|
|||
g_assert (klass->identify_tag != NULL);
|
||||
g_assert (klass->parse_tag != NULL);
|
||||
|
||||
available = gst_buffer_get_size (collect);
|
||||
|
||||
if (available < klass->min_start_size) {
|
||||
GST_DEBUG_OBJECT (demux, "Only %u bytes available, but %u needed "
|
||||
"to identify tag", available, klass->min_start_size);
|
||||
return; /* wait for more data */
|
||||
}
|
||||
|
||||
if (!klass->identify_tag (demux, collect, TRUE, &tagsize)) {
|
||||
GST_DEBUG_OBJECT (demux, "Could not identify start tag");
|
||||
demux->priv->state = GST_TAG_DEMUX_TYPEFINDING;
|
||||
return;
|
||||
}
|
||||
|
||||
demux->priv->tagsize = tagsize;
|
||||
|
||||
/* need to set offset of first buffer to 0 or trimming won't work */
|
||||
if (!GST_BUFFER_OFFSET_IS_VALID (collect)) {
|
||||
GST_WARNING_OBJECT (demux, "Fixing up first buffer without offset");
|
||||
|
@ -599,18 +644,12 @@ gst_tag_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||
demux->priv->segment.position += GST_BUFFER_DURATION (buf);
|
||||
}
|
||||
|
||||
if (demux->priv->collect == NULL) {
|
||||
demux->priv->collect = buf;
|
||||
} else {
|
||||
demux->priv->collect = gst_buffer_append (demux->priv->collect, buf);
|
||||
}
|
||||
demux->priv->collect_size += size;
|
||||
gst_adapter_push (demux->priv->adapter, buf);
|
||||
buf = NULL;
|
||||
|
||||
switch (demux->priv->state) {
|
||||
case GST_TAG_DEMUX_READ_START_TAG:
|
||||
demux->priv->collect = gst_buffer_make_writable (demux->priv->collect);
|
||||
gst_tag_demux_chain_parse_tag (demux, demux->priv->collect);
|
||||
gst_tag_demux_chain_parse_tag (demux);
|
||||
if (demux->priv->state != GST_TAG_DEMUX_TYPEFINDING)
|
||||
break;
|
||||
/* Fall-through */
|
||||
|
@ -620,6 +659,8 @@ gst_tag_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||
gsize typefind_size;
|
||||
GstCaps *caps;
|
||||
|
||||
update_collected (demux);
|
||||
|
||||
if (demux->priv->collect_size <
|
||||
TYPE_FIND_MIN_SIZE + demux->priv->strip_start)
|
||||
break; /* Go get more data first */
|
||||
|
@ -672,6 +713,8 @@ gst_tag_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||
GstBuffer *outbuf = NULL;
|
||||
gsize outbuf_size;
|
||||
|
||||
update_collected (demux);
|
||||
|
||||
/* Trim the buffer and adjust offset */
|
||||
if (demux->priv->collect) {
|
||||
outbuf = demux->priv->collect;
|
||||
|
|
Loading…
Reference in a new issue