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
@ -75,6 +75,7 @@
|
|||||||
#include "gsttagdemux.h"
|
#include "gsttagdemux.h"
|
||||||
|
|
||||||
#include <gst/base/gsttypefindhelper.h>
|
#include <gst/base/gsttypefindhelper.h>
|
||||||
|
#include <gst/base/gstadapter.h>
|
||||||
#include <gst/gst-i18n-plugin.h>
|
#include <gst/gst-i18n-plugin.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -101,8 +102,10 @@ struct _GstTagDemuxPrivate
|
|||||||
gint64 upstream_size;
|
gint64 upstream_size;
|
||||||
|
|
||||||
GstTagDemuxState state;
|
GstTagDemuxState state;
|
||||||
|
GstAdapter *adapter;
|
||||||
GstBuffer *collect;
|
GstBuffer *collect;
|
||||||
gsize collect_size;
|
gsize collect_size;
|
||||||
|
guint tagsize;
|
||||||
GstCaps *src_caps;
|
GstCaps *src_caps;
|
||||||
|
|
||||||
GstTagList *event_tags;
|
GstTagList *event_tags;
|
||||||
@ -266,6 +269,8 @@ gst_tag_demux_reset (GstTagDemux * tagdemux)
|
|||||||
|
|
||||||
gst_buffer_replace (buffer_p, NULL);
|
gst_buffer_replace (buffer_p, NULL);
|
||||||
tagdemux->priv->collect_size = 0;
|
tagdemux->priv->collect_size = 0;
|
||||||
|
tagdemux->priv->tagsize = 0;
|
||||||
|
gst_adapter_clear (tagdemux->priv->adapter);
|
||||||
gst_caps_replace (caps_p, NULL);
|
gst_caps_replace (caps_p, NULL);
|
||||||
|
|
||||||
if (tagdemux->priv->event_tags) {
|
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_pad_use_fixed_caps (demux->priv->srcpad);
|
||||||
gst_element_add_pad (GST_ELEMENT (demux), demux->priv->srcpad);
|
gst_element_add_pad (GST_ELEMENT (demux), demux->priv->srcpad);
|
||||||
|
|
||||||
|
demux->priv->adapter = gst_adapter_new ();
|
||||||
gst_tag_demux_reset (demux);
|
gst_tag_demux_reset (demux);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,6 +343,10 @@ gst_tag_demux_dispose (GObject * object)
|
|||||||
GstTagDemux *tagdemux = GST_TAG_DEMUX (object);
|
GstTagDemux *tagdemux = GST_TAG_DEMUX (object);
|
||||||
|
|
||||||
gst_tag_demux_reset (tagdemux);
|
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);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@ -487,17 +497,58 @@ no_out_buffer_start:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
GstTagDemuxResult parse_ret;
|
||||||
GstTagDemuxClass *klass;
|
GstTagDemuxClass *klass;
|
||||||
guint tagsize = 0;
|
guint tagsize = 0;
|
||||||
guint available;
|
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));
|
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,
|
/* If we receive a buffer that's from the middle of the file,
|
||||||
* we can't read tags so move to typefinding */
|
* we can't read tags so move to typefinding */
|
||||||
if (GST_BUFFER_OFFSET_IS_VALID (collect) && GST_BUFFER_OFFSET (collect) != 0) {
|
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->identify_tag != NULL);
|
||||||
g_assert (klass->parse_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)) {
|
if (!klass->identify_tag (demux, collect, TRUE, &tagsize)) {
|
||||||
GST_DEBUG_OBJECT (demux, "Could not identify start tag");
|
GST_DEBUG_OBJECT (demux, "Could not identify start tag");
|
||||||
demux->priv->state = GST_TAG_DEMUX_TYPEFINDING;
|
demux->priv->state = GST_TAG_DEMUX_TYPEFINDING;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
demux->priv->tagsize = tagsize;
|
||||||
|
|
||||||
/* need to set offset of first buffer to 0 or trimming won't work */
|
/* need to set offset of first buffer to 0 or trimming won't work */
|
||||||
if (!GST_BUFFER_OFFSET_IS_VALID (collect)) {
|
if (!GST_BUFFER_OFFSET_IS_VALID (collect)) {
|
||||||
GST_WARNING_OBJECT (demux, "Fixing up first buffer without offset");
|
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);
|
demux->priv->segment.position += GST_BUFFER_DURATION (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demux->priv->collect == NULL) {
|
gst_adapter_push (demux->priv->adapter, buf);
|
||||||
demux->priv->collect = buf;
|
|
||||||
} else {
|
|
||||||
demux->priv->collect = gst_buffer_append (demux->priv->collect, buf);
|
|
||||||
}
|
|
||||||
demux->priv->collect_size += size;
|
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
|
|
||||||
switch (demux->priv->state) {
|
switch (demux->priv->state) {
|
||||||
case GST_TAG_DEMUX_READ_START_TAG:
|
case GST_TAG_DEMUX_READ_START_TAG:
|
||||||
demux->priv->collect = gst_buffer_make_writable (demux->priv->collect);
|
gst_tag_demux_chain_parse_tag (demux);
|
||||||
gst_tag_demux_chain_parse_tag (demux, demux->priv->collect);
|
|
||||||
if (demux->priv->state != GST_TAG_DEMUX_TYPEFINDING)
|
if (demux->priv->state != GST_TAG_DEMUX_TYPEFINDING)
|
||||||
break;
|
break;
|
||||||
/* Fall-through */
|
/* Fall-through */
|
||||||
@ -620,6 +659,8 @@ gst_tag_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||||||
gsize typefind_size;
|
gsize typefind_size;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
|
update_collected (demux);
|
||||||
|
|
||||||
if (demux->priv->collect_size <
|
if (demux->priv->collect_size <
|
||||||
TYPE_FIND_MIN_SIZE + demux->priv->strip_start)
|
TYPE_FIND_MIN_SIZE + demux->priv->strip_start)
|
||||||
break; /* Go get more data first */
|
break; /* Go get more data first */
|
||||||
@ -672,6 +713,8 @@ gst_tag_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||||||
GstBuffer *outbuf = NULL;
|
GstBuffer *outbuf = NULL;
|
||||||
gsize outbuf_size;
|
gsize outbuf_size;
|
||||||
|
|
||||||
|
update_collected (demux);
|
||||||
|
|
||||||
/* Trim the buffer and adjust offset */
|
/* Trim the buffer and adjust offset */
|
||||||
if (demux->priv->collect) {
|
if (demux->priv->collect) {
|
||||||
outbuf = demux->priv->collect;
|
outbuf = demux->priv->collect;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user