tags: port to new metadata and memory API

This commit is contained in:
Wim Taymans 2011-03-25 19:52:30 +01:00
parent 95f7fd8edf
commit 41025681bc
7 changed files with 253 additions and 155 deletions

View file

@ -35,21 +35,13 @@
#include "gstnetbuffer.h"
static void
meta_net_address_transform (GstBuffer * transbuf, GstMetaNetAddress * meta,
GstBuffer * buffer, GstMetaTransformData * data)
meta_net_address_copy (GstBuffer * copybuf, GstMetaNetAddress * meta,
GstBuffer * buffer, gsize offset, gsize size)
{
GstMetaNetAddress *naddr;
switch (data->type) {
case GST_META_TRANSFORM_TRIM:
case GST_META_TRANSFORM_MAKE_WRITABLE:
case GST_META_TRANSFORM_COPY:
default:
/* always copy */
naddr = gst_buffer_add_meta_net_address (transbuf);
memcpy (&naddr->naddr, &meta->naddr, sizeof (meta->naddr));
break;
}
naddr = gst_buffer_add_meta_net_address (copybuf);
memcpy (&naddr->naddr, &meta->naddr, sizeof (meta->naddr));
}
const GstMetaInfo *
@ -62,7 +54,8 @@ gst_meta_net_address_get_info (void)
sizeof (GstMetaNetAddress),
(GstMetaInitFunction) NULL,
(GstMetaFreeFunction) NULL,
(GstMetaTransformFunction) meta_net_address_transform,
(GstMetaCopyFunction) meta_net_address_copy,
(GstMetaTransformFunction) NULL,
(GstMetaSerializeFunction) NULL, (GstMetaDeserializeFunction) NULL);
}
return meta_info;

View file

@ -231,7 +231,7 @@ struct _GstExifWriter
struct _GstExifReader
{
GstTagList *taglist;
const GstBuffer *buffer;
GstBuffer *buffer;
guint32 base_offset;
gint byte_order;
@ -451,7 +451,7 @@ static const GstExifTagMatch tag_map_gps[] = {
/* GstExifReader functions */
static void
gst_exif_reader_init (GstExifReader * reader, gint byte_order,
const GstBuffer * buf, guint32 base_offset)
GstBuffer * buf, guint32 base_offset)
{
reader->taglist = gst_tag_list_new ();
reader->buffer = buf;
@ -849,9 +849,10 @@ write_exif_undefined_tag_from_taglist (GstExifWriter * writer,
const GstTagList * taglist, const GstExifTagMatch * exiftag)
{
const GValue *value;
const guint8 *data = NULL;
gint size = 0;
guint8 *data = NULL;
gsize size = 0;
gint tag_size = gst_tag_list_get_tag_size (taglist, exiftag->gst_tag);
GstBuffer *buf = NULL;
if (tag_size != 1) {
GST_WARNING ("Only the first item in the taglist will be serialized");
@ -868,10 +869,8 @@ write_exif_undefined_tag_from_taglist (GstExifWriter * writer,
break;
default:
if (G_VALUE_TYPE (value) == GST_TYPE_BUFFER) {
GstBuffer *buf = gst_value_get_buffer (value);
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
buf = gst_value_get_buffer (value);
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
} else {
GST_WARNING ("Conversion from %s to raw data not supported",
G_VALUE_TYPE_NAME (value));
@ -879,10 +878,11 @@ write_exif_undefined_tag_from_taglist (GstExifWriter * writer,
break;
}
if (size == 0)
return;
if (size > 0)
write_exif_undefined_tag (writer, exiftag->exif_tag, data, size);
write_exif_undefined_tag (writer, exiftag->exif_tag, data, size);
if (buf)
gst_buffer_unmap (buf, data, size);
}
static void
@ -1122,6 +1122,9 @@ parse_exif_ascii_tag (GstExifReader * reader, const GstExifTagMatch * tag,
guint32 real_offset;
if (count > 4) {
guint8 *data;
gsize size;
if (offset < reader->base_offset) {
GST_WARNING ("Offset is smaller (%u) than base offset (%u)", offset,
reader->base_offset);
@ -1129,15 +1132,17 @@ parse_exif_ascii_tag (GstExifReader * reader, const GstExifTagMatch * tag,
}
real_offset = offset - reader->base_offset;
if (real_offset >= GST_BUFFER_SIZE (reader->buffer)) {
data = gst_buffer_map (reader->buffer, &size, NULL, GST_MAP_READ);
if (real_offset >= size) {
GST_WARNING ("Invalid offset %u for buffer of size %u, not adding tag %s",
real_offset, GST_BUFFER_SIZE (reader->buffer), tag->gst_tag);
real_offset, size, tag->gst_tag);
gst_buffer_unmap (reader->buffer, data, size);
return;
}
str =
g_strndup ((gchar *) (GST_BUFFER_DATA (reader->buffer) + real_offset),
count);
str = g_strndup ((gchar *) (data + real_offset), count);
gst_buffer_unmap (reader->buffer, data, size);
} else {
str = g_strndup ((gchar *) offset_as_data, count);
}
@ -1198,6 +1203,9 @@ parse_exif_undefined_tag (GstExifReader * reader, const GstExifTagMatch * tag,
guint32 real_offset;
if (count > 4) {
guint8 *bdata;
gsize bsize;
if (offset < reader->base_offset) {
GST_WARNING ("Offset is smaller (%u) than base offset (%u)", offset,
reader->base_offset);
@ -1205,16 +1213,22 @@ parse_exif_undefined_tag (GstExifReader * reader, const GstExifTagMatch * tag,
}
real_offset = offset - reader->base_offset;
if (real_offset >= GST_BUFFER_SIZE (reader->buffer)) {
bdata = gst_buffer_map (reader->buffer, &bsize, NULL, GST_MAP_READ);
if (real_offset >= bsize) {
GST_WARNING ("Invalid offset %u for buffer of size %u, not adding tag %s",
real_offset, GST_BUFFER_SIZE (reader->buffer), tag->gst_tag);
real_offset, bsize, tag->gst_tag);
gst_buffer_unmap (reader->buffer, bdata, bsize);
return;
}
/* +1 because it could be a string without the \0 */
data = malloc (sizeof (guint8) * count + 1);
memcpy (data, GST_BUFFER_DATA (reader->buffer) + real_offset, count);
memcpy (data, bdata + real_offset, count);
data[count] = 0;
gst_buffer_unmap (reader->buffer, bdata, bsize);
} else {
data = malloc (sizeof (guint8) * count + 1);
memcpy (data, (guint8 *) offset_as_data, count);
@ -1226,9 +1240,8 @@ parse_exif_undefined_tag (GstExifReader * reader, const GstExifTagMatch * tag,
GstBuffer *buf;
buf = gst_buffer_new ();
GST_BUFFER_DATA (buf) = data;
GST_BUFFER_MALLOCDATA (buf) = data;
GST_BUFFER_SIZE (buf) = count;
gst_buffer_take_memory (buf,
gst_memory_new_wrapped (0, data, g_free, count, 0, count));
data = NULL;
gst_tag_list_add (reader->taglist, GST_TAG_MERGE_APPEND, tag->gst_tag,
@ -1254,6 +1267,8 @@ exif_reader_read_rational_tag (GstExifReader * exif_reader,
guint32 real_offset;
gint32 frac_n = 0;
gint32 frac_d = 0;
guint8 *data;
gsize size;
if (count > 1) {
GST_WARNING ("Rationals with multiple entries are not supported");
@ -1265,13 +1280,15 @@ exif_reader_read_rational_tag (GstExifReader * exif_reader,
}
real_offset = offset - exif_reader->base_offset;
if (real_offset >= GST_BUFFER_SIZE (exif_reader->buffer)) {
GST_WARNING ("Invalid offset %u for buffer of size %u",
real_offset, GST_BUFFER_SIZE (exif_reader->buffer));
return FALSE;
data = gst_buffer_map (exif_reader->buffer, &size, NULL, GST_MAP_READ);
if (real_offset >= size) {
GST_WARNING ("Invalid offset %u for buffer of size %u", real_offset, size);
goto reader_fail;
}
gst_byte_reader_init_from_buffer (&data_reader, exif_reader->buffer);
gst_byte_reader_init (&data_reader, data, size);
if (!gst_byte_reader_set_pos (&data_reader, real_offset))
goto reader_fail;
@ -1305,10 +1322,13 @@ exif_reader_read_rational_tag (GstExifReader * exif_reader,
if (_frac_d)
*_frac_d = frac_d;
gst_buffer_unmap (exif_reader->buffer, data, size);
return TRUE;
reader_fail:
GST_WARNING ("Failed to read from byte reader. (Buffer too short?)");
gst_buffer_unmap (exif_reader->buffer, data, size);
return FALSE;
}
@ -1408,12 +1428,17 @@ write_exif_ifd (const GstTagList * taglist, gboolean byte_order,
}
if (inner_ifd) {
guint8 *data;
gsize size;
GST_DEBUG ("Adding inner ifd: %x", tag_map[i].exif_tag);
gst_exif_writer_write_tag_header (&writer, tag_map[i].exif_tag,
EXIF_TYPE_LONG, 1,
gst_byte_writer_get_size (&writer.datawriter), FALSE);
gst_byte_writer_put_data (&writer.datawriter,
GST_BUFFER_DATA (inner_ifd), GST_BUFFER_SIZE (inner_ifd));
data = gst_buffer_map (inner_ifd, &size, NULL, GST_MAP_READ);
gst_byte_writer_put_data (&writer.datawriter, data, size);
gst_buffer_unmap (inner_ifd, data, size);
gst_buffer_unref (inner_ifd);
}
continue;
@ -1483,15 +1508,17 @@ parse_exif_ifd (GstExifReader * exif_reader, gint buf_offset,
GstByteReader reader;
guint16 entries = 0;
guint16 i;
guint8 *data;
gsize size;
g_return_val_if_fail (exif_reader->byte_order == G_LITTLE_ENDIAN
|| exif_reader->byte_order == G_BIG_ENDIAN, FALSE);
gst_byte_reader_init_from_buffer (&reader, exif_reader->buffer);
if (!gst_byte_reader_set_pos (&reader, buf_offset)) {
GST_WARNING ("Buffer offset invalid when parsing exif ifd");
return FALSE;
}
data = gst_buffer_map (exif_reader->buffer, &size, NULL, GST_MAP_READ);
gst_byte_reader_init (&reader, data, size);
if (!gst_byte_reader_set_pos (&reader, buf_offset))
goto invalid_offset;
/* read the IFD entries number */
if (exif_reader->byte_order == G_LITTLE_ENDIAN) {
@ -1597,12 +1624,20 @@ parse_exif_ifd (GstExifReader * exif_reader, gint buf_offset,
}
}
}
gst_buffer_unmap (exif_reader->buffer, data, size);
return TRUE;
invalid_offset:
{
GST_WARNING ("Buffer offset invalid when parsing exif ifd");
gst_buffer_unmap (exif_reader->buffer, data, size);
return FALSE;
}
read_error:
{
GST_WARNING ("Failed to parse the exif ifd");
gst_buffer_unmap (exif_reader->buffer, data, size);
return FALSE;
}
}
@ -1643,14 +1678,18 @@ gst_tag_list_to_exif_buffer_with_tiff_header (const GstTagList * taglist)
{
GstBuffer *ifd;
GstByteWriter writer;
guint size;
gsize size;
guint8 *data;
ifd = gst_tag_list_to_exif_buffer (taglist, G_BYTE_ORDER, 8);
if (ifd == NULL) {
GST_WARNING ("Failed to create exif buffer");
return NULL;
}
size = TIFF_HEADER_SIZE + GST_BUFFER_SIZE (ifd);
data = gst_buffer_map (ifd, &size, NULL, GST_MAP_READ);
size += TIFF_HEADER_SIZE;
/* TODO what is the correct endianness here? */
gst_byte_writer_init_with_size (&writer, size, FALSE);
@ -1664,17 +1703,19 @@ gst_tag_list_to_exif_buffer_with_tiff_header (const GstTagList * taglist)
gst_byte_writer_put_uint16_be (&writer, 42);
gst_byte_writer_put_uint32_be (&writer, 8);
}
if (!gst_byte_writer_put_data (&writer, GST_BUFFER_DATA (ifd),
GST_BUFFER_SIZE (ifd))) {
if (!gst_byte_writer_put_data (&writer, data, size)) {
GST_WARNING ("Byte writer size mismatch");
/* reaching here is a programming error because we should have a buffer
* large enough */
g_assert_not_reached ();
gst_buffer_unmap (ifd, data, size);
gst_buffer_unref (ifd);
gst_byte_writer_reset (&writer);
return NULL;
}
gst_buffer_unmap (ifd, data, size);
gst_buffer_unref (ifd);
return gst_byte_writer_reset_and_get_buffer (&writer);
}
@ -1694,7 +1735,7 @@ gst_tag_list_to_exif_buffer_with_tiff_header (const GstTagList * taglist)
* Since: 0.10.30
*/
GstTagList *
gst_tag_list_from_exif_buffer (const GstBuffer * buffer, gint byte_order,
gst_tag_list_from_exif_buffer (GstBuffer * buffer, gint byte_order,
guint32 base_offset)
{
GstExifReader reader;
@ -1727,7 +1768,7 @@ read_error:
* Since: 0.10.30
*/
GstTagList *
gst_tag_list_from_exif_buffer_with_tiff_header (const GstBuffer * buffer)
gst_tag_list_from_exif_buffer_with_tiff_header (GstBuffer * buffer)
{
GstByteReader reader;
guint16 fortytwo = 42;
@ -1735,11 +1776,14 @@ gst_tag_list_from_exif_buffer_with_tiff_header (const GstBuffer * buffer)
guint32 offset;
GstTagList *taglist = NULL;
GstBuffer *subbuffer;
guint8 *data, *sdata;
gsize size, ssize;
GST_LOG ("Parsing exif tags with tiff header of size %u",
GST_BUFFER_SIZE (buffer));
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
gst_byte_reader_init_from_buffer (&reader, buffer);
GST_LOG ("Parsing exif tags with tiff header of size %u", size);
gst_byte_reader_init (&reader, data, size);
GST_LOG ("Parsing the tiff header");
if (!gst_byte_reader_get_uint16_be (&reader, &endianness)) {
@ -1754,32 +1798,42 @@ gst_tag_list_from_exif_buffer_with_tiff_header (const GstBuffer * buffer)
if (!gst_byte_reader_get_uint16_be (&reader, &fortytwo) ||
!gst_byte_reader_get_uint32_be (&reader, &offset))
goto byte_reader_fail;
} else {
GST_WARNING ("Invalid endianness number %u", endianness);
return NULL;
}
} else
goto invalid_endianness;
if (fortytwo != 42) {
GST_WARNING ("Invalid magic number %u, should be 42", fortytwo);
return NULL;
}
if (fortytwo != 42)
goto invalid_magic;
subbuffer = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buffer) -
(TIFF_HEADER_SIZE - 2));
memcpy (GST_BUFFER_DATA (subbuffer),
GST_BUFFER_DATA (buffer) + TIFF_HEADER_SIZE,
GST_BUFFER_SIZE (buffer) - TIFF_HEADER_SIZE);
subbuffer = gst_buffer_new_and_alloc (size - (TIFF_HEADER_SIZE - 2));
sdata = gst_buffer_map (subbuffer, &ssize, NULL, GST_MAP_WRITE);
memcpy (sdata, data + TIFF_HEADER_SIZE, size - TIFF_HEADER_SIZE);
gst_buffer_unmap (subbuffer, sdata, ssize);
taglist = gst_tag_list_from_exif_buffer (subbuffer,
endianness == TIFF_LITTLE_ENDIAN ? G_LITTLE_ENDIAN : G_BIG_ENDIAN, 8);
gst_buffer_unref (subbuffer);
done:
gst_buffer_unmap (buffer, data, size);
return taglist;
byte_reader_fail:
{
GST_WARNING ("Failed to read values from buffer");
return NULL;
goto done;
}
invalid_endianness:
{
GST_WARNING ("Invalid endianness number %u", endianness);
goto done;
}
invalid_magic:
{
GST_WARNING ("Invalid magic number %u, should be 42", fortytwo);
goto done;
}
}
@ -1879,6 +1933,8 @@ deserialize_geo_coordinate (GstExifReader * exif_reader,
gdouble degrees;
gdouble minutes;
gdouble seconds;
guint8 *data = NULL;
gsize size = 0;
GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag,
exiftag->exif_tag);
@ -1935,8 +1991,11 @@ deserialize_geo_coordinate (GstExifReader * exif_reader,
return ret;
}
data = gst_buffer_map (exif_reader->buffer, &size, NULL, GST_MAP_READ);
/* now parse the fractions */
gst_byte_reader_init_from_buffer (&fractions_reader, exif_reader->buffer);
gst_byte_reader_init (&fractions_reader, data, size);
if (!gst_byte_reader_set_pos (&fractions_reader,
next_tagdata.offset - exif_reader->base_offset))
goto reader_fail;
@ -1958,6 +2017,7 @@ deserialize_geo_coordinate (GstExifReader * exif_reader,
!gst_byte_reader_get_uint32_be (&fractions_reader, &seconds_d))
goto reader_fail;
}
gst_buffer_unmap (exif_reader->buffer, data, size);
GST_DEBUG ("Read degrees fraction for tag %s: %u/%u %u/%u %u/%u",
exiftag->gst_tag, degrees_n, degrees_d, minutes_n, minutes_d,
@ -1979,6 +2039,8 @@ deserialize_geo_coordinate (GstExifReader * exif_reader,
reader_fail:
GST_WARNING ("Failed to read fields from buffer (too short?)");
if (data)
gst_buffer_unmap (exif_reader->buffer, data, size);
return ret;
}

View file

@ -102,6 +102,7 @@ struct _GstTagDemuxPrivate
GstTagDemuxState state;
GstBuffer *collect;
gsize collect_size;
GstCaps *src_caps;
GstTagList *event_tags;
@ -254,6 +255,7 @@ gst_tag_demux_reset (GstTagDemux * tagdemux)
tagdemux->priv->send_tag_event = FALSE;
gst_buffer_replace (buffer_p, NULL);
tagdemux->priv->collect_size = 0;
gst_caps_replace (caps_p, NULL);
gst_tag_demux_remove_srcpad (tagdemux);
@ -388,18 +390,23 @@ gst_tag_demux_remove_srcpad (GstTagDemux * demux)
* also return TRUE and set *buf_ref to NULL if the buffer was before
* the start of the data */
static gboolean
gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref)
gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref,
gsize * buf_size)
{
GstBuffer *buf = *buf_ref;
guint trim_start = 0;
guint out_size = GST_BUFFER_SIZE (buf);
guint64 out_offset = GST_BUFFER_OFFSET (buf);
guint out_size, bsize;
guint64 out_offset, boffset;
gboolean need_sub = FALSE;
bsize = out_size = gst_buffer_get_size (buf);
boffset = out_offset = GST_BUFFER_OFFSET (buf);
/* Adjust offset and length */
if (!GST_BUFFER_OFFSET_IS_VALID (buf)) {
/* Can't change anything without an offset */
*buf_size = bsize;
return TRUE;
}
@ -439,21 +446,22 @@ gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref)
}
if (need_sub == TRUE) {
if (out_size != GST_BUFFER_SIZE (buf) || !gst_buffer_is_writable (buf)) {
if (out_size != bsize || !gst_buffer_is_writable (buf)) {
GstBuffer *sub;
GST_DEBUG_OBJECT (tagdemux, "Sub-buffering to trim size %d offset %"
G_GINT64_FORMAT " to %d offset %" G_GINT64_FORMAT,
GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf), out_size, out_offset);
bsize, boffset, out_size, out_offset);
sub = gst_buffer_create_sub (buf, trim_start, out_size);
g_return_val_if_fail (sub != NULL, FALSE);
gst_buffer_unref (buf);
*buf_ref = buf = sub;
*buf_size = out_size;
} else {
GST_DEBUG_OBJECT (tagdemux, "Adjusting buffer from size %d offset %"
G_GINT64_FORMAT " to %d offset %" G_GINT64_FORMAT,
GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf), out_size, out_offset);
bsize, boffset, out_size, out_offset);
}
GST_BUFFER_OFFSET (buf) = out_offset;
@ -485,7 +493,7 @@ gst_tag_demux_chain_parse_tag (GstTagDemux * demux, GstBuffer * collect)
guint tagsize = 0;
guint available;
g_assert (gst_buffer_is_metadata_writable (collect));
g_assert (gst_buffer_is_writable (collect));
klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux));
@ -501,7 +509,7 @@ 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_SIZE (collect);
available = gst_buffer_get_size (collect);
if (available < klass->min_start_size) {
GST_DEBUG_OBJECT (demux, "Only %u bytes available, but %u needed "
@ -535,13 +543,13 @@ gst_tag_demux_chain_parse_tag (GstTagDemux * demux, GstBuffer * collect)
return; /* wait for more data */
}
saved_size = GST_BUFFER_SIZE (collect);
GST_BUFFER_SIZE (collect) = tagsize;
saved_size = gst_buffer_get_size (collect);
gst_buffer_set_size (collect, tagsize);
newsize = tagsize;
parse_ret = klass->parse_tag (demux, collect, TRUE, &newsize, &tags);
GST_BUFFER_SIZE (collect) = saved_size;
gst_buffer_set_size (collect, saved_size);
switch (parse_ret) {
case GST_TAG_DEMUX_RESULT_OK:
@ -572,14 +580,17 @@ static GstFlowReturn
gst_tag_demux_chain (GstPad * pad, GstBuffer * buf)
{
GstTagDemux *demux;
gsize size;
demux = GST_TAG_DEMUX (GST_PAD_PARENT (pad));
size = gst_buffer_get_size (buf);
/* Update our segment last_stop info */
if (demux->priv->segment.format == GST_FORMAT_BYTES) {
if (GST_BUFFER_OFFSET_IS_VALID (buf))
demux->priv->segment.last_stop = GST_BUFFER_OFFSET (buf);
demux->priv->segment.last_stop += GST_BUFFER_SIZE (buf);
demux->priv->segment.last_stop += size;
} else if (demux->priv->segment.format == GST_FORMAT_TIME) {
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf))
demux->priv->segment.last_stop = GST_BUFFER_TIMESTAMP (buf);
@ -592,12 +603,12 @@ gst_tag_demux_chain (GstPad * pad, GstBuffer * buf)
} else {
demux->priv->collect = gst_buffer_join (demux->priv->collect, buf);
}
demux->priv->collect_size += size;
buf = NULL;
switch (demux->priv->state) {
case GST_TAG_DEMUX_READ_START_TAG:
demux->priv->collect =
gst_buffer_make_metadata_writable (demux->priv->collect);
demux->priv->collect = gst_buffer_make_writable (demux->priv->collect);
gst_tag_demux_chain_parse_tag (demux, demux->priv->collect);
if (demux->priv->state != GST_TAG_DEMUX_TYPEFINDING)
break;
@ -605,19 +616,20 @@ gst_tag_demux_chain (GstPad * pad, GstBuffer * buf)
case GST_TAG_DEMUX_TYPEFINDING:{
GstTypeFindProbability probability = 0;
GstBuffer *typefind_buf = NULL;
gsize typefind_size;
GstCaps *caps;
if (GST_BUFFER_SIZE (demux->priv->collect) <
if (demux->priv->collect_size <
TYPE_FIND_MIN_SIZE + demux->priv->strip_start)
break; /* Go get more data first */
GST_DEBUG_OBJECT (demux, "Typefinding with size %d",
GST_BUFFER_SIZE (demux->priv->collect));
demux->priv->collect_size);
/* Trim the buffer and adjust offset for typefinding */
typefind_buf = demux->priv->collect;
gst_buffer_ref (typefind_buf);
if (!gst_tag_demux_trim_buffer (demux, &typefind_buf))
if (!gst_tag_demux_trim_buffer (demux, &typefind_buf, &typefind_size))
return GST_FLOW_UNEXPECTED;
if (typefind_buf == NULL)
@ -627,7 +639,7 @@ gst_tag_demux_chain (GstPad * pad, GstBuffer * buf)
typefind_buf, &probability);
if (caps == NULL) {
if (GST_BUFFER_SIZE (typefind_buf) < TYPE_FIND_MAX_SIZE) {
if (typefind_size < TYPE_FIND_MAX_SIZE) {
/* Just break for more data */
gst_buffer_unref (typefind_buf);
return GST_FLOW_OK;
@ -639,6 +651,7 @@ gst_tag_demux_chain (GstPad * pad, GstBuffer * buf)
gst_buffer_unref (typefind_buf);
gst_buffer_unref (demux->priv->collect);
demux->priv->collect = NULL;
demux->priv->collect_size = 0;
return GST_FLOW_ERROR;
}
gst_buffer_unref (typefind_buf);
@ -660,12 +673,14 @@ gst_tag_demux_chain (GstPad * pad, GstBuffer * buf)
}
case GST_TAG_DEMUX_STREAMING:{
GstBuffer *outbuf = NULL;
gsize outbuf_size;
/* Trim the buffer and adjust offset */
if (demux->priv->collect) {
outbuf = demux->priv->collect;
demux->priv->collect = NULL;
if (!gst_tag_demux_trim_buffer (demux, &outbuf))
demux->priv->collect_size = 0;
if (!gst_tag_demux_trim_buffer (demux, &outbuf, &outbuf_size))
return GST_FLOW_UNEXPECTED;
}
if (outbuf) {
@ -693,7 +708,7 @@ gst_tag_demux_chain (GstPad * pad, GstBuffer * buf)
}
/* Ensure the caps are set correctly */
outbuf = gst_buffer_make_metadata_writable (outbuf);
outbuf = gst_buffer_make_writable (outbuf);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (demux->priv->srcpad));
GST_LOG_OBJECT (demux, "Pushing buffer %p", outbuf);
@ -885,6 +900,7 @@ gst_tag_demux_pull_end_tag (GstTagDemux * demux, GstTagList ** tags)
gboolean res = FALSE;
guint64 offset;
guint tagsize;
gsize bsize;
klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux));
@ -913,9 +929,11 @@ gst_tag_demux_pull_end_tag (GstTagDemux * demux, GstTagList ** tags)
goto done;
}
if (GST_BUFFER_SIZE (buffer) < klass->min_end_size) {
bsize = gst_buffer_get_size (buffer);
if (bsize < klass->min_end_size) {
GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file "
"(required: %u bytes)", GST_BUFFER_SIZE (buffer), klass->min_end_size);
"(required: %u bytes)", bsize, klass->min_end_size);
goto done;
}
@ -937,7 +955,7 @@ gst_tag_demux_pull_end_tag (GstTagDemux * demux, GstTagList ** tags)
g_assert (tagsize >= klass->min_end_size);
/* Get buffer that's exactly the requested size */
if (GST_BUFFER_SIZE (buffer) != tagsize) {
if (bsize != tagsize) {
gst_buffer_unref (buffer);
buffer = NULL;
@ -953,22 +971,24 @@ gst_tag_demux_pull_end_tag (GstTagDemux * demux, GstTagList ** tags)
goto done;
}
if (GST_BUFFER_SIZE (buffer) < tagsize) {
bsize = gst_buffer_get_size (buffer);
if (bsize < tagsize) {
GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file",
GST_BUFFER_SIZE (buffer));
bsize);
goto done;
}
}
GST_BUFFER_OFFSET (buffer) = offset;
saved_size = GST_BUFFER_SIZE (buffer);
GST_BUFFER_SIZE (buffer) = tagsize;
saved_size = bsize;
gst_buffer_set_size (buffer, tagsize);
newsize = tagsize;
parse_ret = klass->parse_tag (demux, buffer, FALSE, &newsize, &new_tags);
GST_BUFFER_SIZE (buffer) = saved_size;
gst_buffer_set_size (buffer, saved_size);
switch (parse_ret) {
case GST_TAG_DEMUX_RESULT_OK:
@ -1015,6 +1035,7 @@ gst_tag_demux_pull_start_tag (GstTagDemux * demux, GstTagList ** tags)
gboolean have_tag;
gboolean res = FALSE;
guint req, tagsize;
gsize bsize;
klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux));
@ -1037,9 +1058,11 @@ gst_tag_demux_pull_start_tag (GstTagDemux * demux, GstTagList ** tags)
goto done;
}
if (GST_BUFFER_SIZE (buffer) < klass->min_start_size) {
bsize = gst_buffer_get_size (buffer);
if (bsize < klass->min_start_size) {
GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file - "
"no tag in this file", GST_BUFFER_SIZE (buffer));
"no tag in this file", bsize);
goto done;
}
@ -1061,7 +1084,7 @@ gst_tag_demux_pull_start_tag (GstTagDemux * demux, GstTagList ** tags)
/* Now pull the entire tag */
g_assert (tagsize >= klass->min_start_size);
if (GST_BUFFER_SIZE (buffer) < tagsize) {
if (bsize < tagsize) {
gst_buffer_unref (buffer);
buffer = NULL;
@ -1072,21 +1095,23 @@ gst_tag_demux_pull_start_tag (GstTagDemux * demux, GstTagList ** tags)
goto done;
}
if (GST_BUFFER_SIZE (buffer) < tagsize) {
bsize = gst_buffer_get_size (buffer);
if (bsize < tagsize) {
GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file",
GST_BUFFER_SIZE (buffer));
bsize);
GST_ELEMENT_ERROR (demux, STREAM, DECODE,
(_("Failed to read tag: not enough data")), (NULL));
goto done;
}
}
saved_size = GST_BUFFER_SIZE (buffer);
GST_BUFFER_SIZE (buffer) = tagsize;
saved_size = bsize;
gst_buffer_set_size (buffer, tagsize);
newsize = tagsize;
parse_ret = klass->parse_tag (demux, buffer, TRUE, &newsize, &new_tags);
GST_BUFFER_SIZE (buffer) = saved_size;
gst_buffer_set_size (buffer, saved_size);
switch (parse_ret) {
case GST_TAG_DEMUX_RESULT_OK:
@ -1272,6 +1297,7 @@ gst_tag_demux_read_range (GstTagDemux * demux,
GstFlowReturn ret;
guint64 in_offset;
guint in_length;
gsize size;
g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
@ -1294,7 +1320,7 @@ gst_tag_demux_read_range (GstTagDemux * demux,
ret = gst_pad_pull_range (demux->priv->sinkpad, in_offset, in_length, buffer);
if (ret == GST_FLOW_OK && *buffer) {
if (!gst_tag_demux_trim_buffer (demux, buffer))
if (!gst_tag_demux_trim_buffer (demux, buffer, &size))
goto read_beyond_end;
/* this should only happen in streaming mode */

View file

@ -365,7 +365,8 @@ convert_failed:
/**
* gst_tag_list_from_vorbiscomment_buffer:
* @buffer: buffer to convert
* @data: data to convert
* @size: size of @data
* @id_data: identification data at start of stream
* @id_data_length: length of identification data
* @vendor_string: pointer to a string that should take the vendor string
@ -378,7 +379,7 @@ convert_failed:
* given vorbiscomment buffer or NULL on error.
*/
GstTagList *
gst_tag_list_from_vorbiscomment_buffer (const GstBuffer * buffer,
gst_tag_list_from_vorbiscomment (const guint8 * data, gsize size,
const guint8 * id_data, const guint id_data_length, gchar ** vendor_string)
{
#define ADVANCE(x) G_STMT_START{ \
@ -394,15 +395,12 @@ gst_tag_list_from_vorbiscomment_buffer (const GstBuffer * buffer,
gchar *cur, *value;
guint cur_size;
guint iterations;
guint8 *data;
guint size, value_len;
guint value_len;
GstTagList *list;
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (id_data != NULL || id_data_length == 0, NULL);
data = GST_BUFFER_DATA (buffer);
size = GST_BUFFER_SIZE (buffer);
list = gst_tag_list_new ();
if (size < 11 || size <= id_data_length + 4)
@ -471,6 +469,8 @@ gst_tag_to_coverart (const GValue * image_value)
GstStructure *mime_struct;
GstBuffer *buffer;
GList *l = NULL;
guint8 *data;
gsize size;
g_return_val_if_fail (image_value != NULL, NULL);
@ -479,12 +479,14 @@ gst_tag_to_coverart (const GValue * image_value)
mime_struct = gst_caps_get_structure (buffer->caps, 0);
mime_type = gst_structure_get_name (mime_struct);
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
if (strcmp (mime_type, "text/uri-list") == 0) {
/* URI reference */
coverart_data = g_strndup ((gchar *) buffer->data, buffer->size);
coverart_data = g_strndup ((gchar *) data, size);
} else {
coverart_data = g_base64_encode (buffer->data, buffer->size);
coverart_data = g_base64_encode (data, size);
}
gst_buffer_unmap (buffer, data, size);
data_result = g_strdup_printf ("COVERART=%s", coverart_data);
mime_result = g_strdup_printf ("COVERARTMIME=%s", mime_type);
@ -647,7 +649,7 @@ gst_tag_list_to_vorbiscomment_buffer (const GstTagList * list,
const gchar * vendor_string)
{
GstBuffer *buffer;
guint8 *data;
guint8 *data, *odata;
guint i;
GList *l;
MyForEach my_data = { 0, 0, NULL };
@ -663,8 +665,9 @@ gst_tag_list_to_vorbiscomment_buffer (const GstTagList * list,
required_size = id_data_length + 4 + vendor_len + 4 + 1;
gst_tag_list_foreach ((GstTagList *) list, write_one_tag, &my_data);
required_size += 4 * my_data.count + my_data.data_count;
buffer = gst_buffer_new_and_alloc (required_size);
data = GST_BUFFER_DATA (buffer);
odata = data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_WRITE);
if (id_data_length > 0) {
memcpy (data, id_data, id_data_length);
data += id_data_length;
@ -692,6 +695,7 @@ gst_tag_list_to_vorbiscomment_buffer (const GstTagList * list,
g_list_foreach (my_data.entries, (GFunc) g_free, NULL);
g_list_free (my_data.entries);
*data = 1;
gst_buffer_unmap (buffer, odata, required_size);
return buffer;
}

View file

@ -1132,11 +1132,11 @@ read_one_tag (GstTagList * list, const gchar * tag, XmpTag * xmptag,
* Since: 0.10.29
*/
GstTagList *
gst_tag_list_from_xmp_buffer (const GstBuffer * buffer)
gst_tag_list_from_xmp_buffer (GstBuffer * buffer)
{
GstTagList *list = NULL;
const gchar *xps, *xp1, *xp2, *xpe, *ns, *ne;
guint len, max_ft_len;
gchar *xps, *xp1, *xp2, *xpe, *ns, *ne;
gsize len, max_ft_len;
gboolean in_tag;
gchar *part, *pp;
guint i;
@ -1157,10 +1157,10 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer)
xmp_tags_initialize ();
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
g_return_val_if_fail (GST_BUFFER_SIZE (buffer) > 0, NULL);
xps = (const gchar *) GST_BUFFER_DATA (buffer);
len = GST_BUFFER_SIZE (buffer);
xps = gst_buffer_map (buffer, &len, NULL, GST_MAP_READ);
g_return_val_if_fail (len > 0, NULL);
xpe = &xps[len + 1];
/* check header and footer */
@ -1365,6 +1365,8 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer)
}
g_free (part);
gst_buffer_unmap (buffer, xps, len);
return list;
/* Errors */
@ -1530,53 +1532,57 @@ GstBuffer *
gst_tag_list_to_xmp_buffer (const GstTagList * list, gboolean read_only)
{
GstBuffer *buffer = NULL;
GString *data = g_string_sized_new (4096);
GString *str = g_string_sized_new (4096);
guint i;
gsize size;
gpointer data;
xmp_tags_initialize ();
g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
/* xmp header */
g_string_append (data,
g_string_append (str,
"<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n");
g_string_append (data,
g_string_append (str,
"<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"GStreamer\">\n");
g_string_append (data,
g_string_append (str,
"<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"");
i = 0;
while (ns_match[i].ns_prefix) {
g_string_append_printf (data, " xmlns:%s=\"%s\"", ns_match[i].ns_prefix,
g_string_append_printf (str, " xmlns:%s=\"%s\"", ns_match[i].ns_prefix,
ns_match[i].ns_uri);
i++;
}
g_string_append (data, ">\n");
g_string_append (data, "<rdf:Description rdf:about=\"\">\n");
g_string_append (str, ">\n");
g_string_append (str, "<rdf:Description rdf:about=\"\">\n");
/* iterate the taglist */
gst_tag_list_foreach (list, write_one_tag, data);
gst_tag_list_foreach (list, write_one_tag, str);
/* xmp footer */
g_string_append (data, "</rdf:Description>\n");
g_string_append (data, "</rdf:RDF>\n");
g_string_append (data, "</x:xmpmeta>\n");
g_string_append (str, "</rdf:Description>\n");
g_string_append (str, "</rdf:RDF>\n");
g_string_append (str, "</x:xmpmeta>\n");
if (!read_only) {
/* the xmp spec recommand to add 2-4KB padding for in-place editable xmp */
guint i;
for (i = 0; i < 32; i++) {
g_string_append (data, " " " "
g_string_append (str, " " " "
" " " " "\n");
}
}
g_string_append_printf (data, "<?xpacket end=\"%c\"?>\n",
g_string_append_printf (str, "<?xpacket end=\"%c\"?>\n",
(read_only ? 'r' : 'w'));
size = str->len + 1;
data = g_string_free (str, FALSE);
buffer = gst_buffer_new ();
GST_BUFFER_SIZE (buffer) = data->len + 1;
GST_BUFFER_DATA (buffer) = (guint8 *) g_string_free (data, FALSE);
GST_BUFFER_MALLOCDATA (buffer) = GST_BUFFER_DATA (buffer);
gst_buffer_take_memory (buffer,
gst_memory_new_wrapped (0, data, g_free, size, 0, size));
return buffer;
}

View file

@ -445,7 +445,8 @@ GList * gst_tag_to_vorbis_comments (const GstTagLis
const gchar * tag);
/* functions to convert GstBuffers with vorbiscomment contents to GstTagLists and back */
GstTagList * gst_tag_list_from_vorbiscomment_buffer (const GstBuffer * buffer,
GstTagList * gst_tag_list_from_vorbiscomment (const guint8 * data,
gsize size,
const guint8 * id_data,
const guint id_data_length,
gchar ** vendor_string);
@ -471,7 +472,7 @@ gboolean gst_tag_list_add_id3_image (GstTagList * tag_list,
guint id3_picture_type);
/* functions to convert GstBuffers with xmp packets contents to GstTagLists and back */
GstTagList * gst_tag_list_from_xmp_buffer (const GstBuffer * buffer);
GstTagList * gst_tag_list_from_xmp_buffer (GstBuffer * buffer);
GstBuffer * gst_tag_list_to_xmp_buffer (const GstTagList * list,
gboolean read_only);
@ -482,12 +483,12 @@ GstBuffer * gst_tag_list_to_exif_buffer (const GstTagList * taglist,
GstBuffer * gst_tag_list_to_exif_buffer_with_tiff_header (const GstTagList * taglist);
GstTagList * gst_tag_list_from_exif_buffer (const GstBuffer * buffer,
GstTagList * gst_tag_list_from_exif_buffer (GstBuffer * buffer,
gint byte_order,
guint32 base_offset);
GstTagList * gst_tag_list_from_exif_buffer_with_tiff_header (
const GstBuffer * buffer);
GstBuffer * buffer);
/* other tag-related functions */

View file

@ -553,10 +553,9 @@ gst_tag_image_data_to_image_buffer (const guint8 * image_data,
guint image_data_len, GstTagImageType image_type)
{
const gchar *name;
GstBuffer *image;
GstCaps *caps;
guint8 *data;
g_return_val_if_fail (image_data != NULL, NULL);
g_return_val_if_fail (image_data_len > 0, NULL);
@ -565,14 +564,14 @@ gst_tag_image_data_to_image_buffer (const guint8 * image_data,
GST_DEBUG ("image data len: %u bytes", image_data_len);
/* allocate space for a NUL terminator for an uri too */
image = gst_buffer_try_new_and_alloc (image_data_len + 1);
if (image == NULL) {
GST_WARNING ("failed to allocate buffer of %d for image", image_data_len);
return NULL;
}
image = gst_buffer_new_and_alloc (image_data_len + 1);
if (image == NULL)
goto alloc_failed;
memcpy (GST_BUFFER_DATA (image), image_data, image_data_len);
GST_BUFFER_DATA (image)[image_data_len] = '\0';
data = gst_buffer_map (image, NULL, NULL, GST_MAP_WRITE);
memcpy (data, image_data, image_data_len);
data[image_data_len] = '\0';
gst_buffer_unmap (image, data, image_data_len + 1);
/* Find GStreamer media type, can't trust declared type */
caps = gst_type_find_helper_for_buffer (NULL, image, NULL);
@ -596,7 +595,7 @@ gst_tag_image_data_to_image_buffer (const guint8 * image_data,
* to keep the original size of the image
*/
if (!g_str_equal (name, "text/uri-list"))
GST_BUFFER_SIZE (image) = image_data_len;
gst_buffer_set_size (image, image_data_len);
if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
GST_LOG ("Setting image type: %d", image_type);
@ -623,4 +622,11 @@ error:
gst_caps_unref (caps);
return NULL;
}
alloc_failed:
{
GST_WARNING ("failed to allocate buffer of %d for image", image_data_len);
gst_buffer_unref (image);
return NULL;
}
}