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" #include "gstnetbuffer.h"
static void static void
meta_net_address_transform (GstBuffer * transbuf, GstMetaNetAddress * meta, meta_net_address_copy (GstBuffer * copybuf, GstMetaNetAddress * meta,
GstBuffer * buffer, GstMetaTransformData * data) GstBuffer * buffer, gsize offset, gsize size)
{ {
GstMetaNetAddress *naddr; GstMetaNetAddress *naddr;
switch (data->type) { naddr = gst_buffer_add_meta_net_address (copybuf);
case GST_META_TRANSFORM_TRIM: memcpy (&naddr->naddr, &meta->naddr, sizeof (meta->naddr));
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;
}
} }
const GstMetaInfo * const GstMetaInfo *
@ -62,7 +54,8 @@ gst_meta_net_address_get_info (void)
sizeof (GstMetaNetAddress), sizeof (GstMetaNetAddress),
(GstMetaInitFunction) NULL, (GstMetaInitFunction) NULL,
(GstMetaFreeFunction) NULL, (GstMetaFreeFunction) NULL,
(GstMetaTransformFunction) meta_net_address_transform, (GstMetaCopyFunction) meta_net_address_copy,
(GstMetaTransformFunction) NULL,
(GstMetaSerializeFunction) NULL, (GstMetaDeserializeFunction) NULL); (GstMetaSerializeFunction) NULL, (GstMetaDeserializeFunction) NULL);
} }
return meta_info; return meta_info;

View file

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

View file

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

View file

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

View file

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

View file

@ -445,7 +445,8 @@ GList * gst_tag_to_vorbis_comments (const GstTagLis
const gchar * tag); const gchar * tag);
/* functions to convert GstBuffers with vorbiscomment contents to GstTagLists and back */ /* 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 guint8 * id_data,
const guint id_data_length, const guint id_data_length,
gchar ** vendor_string); gchar ** vendor_string);
@ -471,7 +472,7 @@ gboolean gst_tag_list_add_id3_image (GstTagList * tag_list,
guint id3_picture_type); guint id3_picture_type);
/* functions to convert GstBuffers with xmp packets contents to GstTagLists and back */ /* 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, GstBuffer * gst_tag_list_to_xmp_buffer (const GstTagList * list,
gboolean read_only); 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); 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, gint byte_order,
guint32 base_offset); guint32 base_offset);
GstTagList * gst_tag_list_from_exif_buffer_with_tiff_header ( GstTagList * gst_tag_list_from_exif_buffer_with_tiff_header (
const GstBuffer * buffer); GstBuffer * buffer);
/* other tag-related functions */ /* 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) guint image_data_len, GstTagImageType image_type)
{ {
const gchar *name; const gchar *name;
GstBuffer *image; GstBuffer *image;
GstCaps *caps; GstCaps *caps;
guint8 *data;
g_return_val_if_fail (image_data != NULL, NULL); g_return_val_if_fail (image_data != NULL, NULL);
g_return_val_if_fail (image_data_len > 0, 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); GST_DEBUG ("image data len: %u bytes", image_data_len);
/* allocate space for a NUL terminator for an uri too */ /* allocate space for a NUL terminator for an uri too */
image = gst_buffer_try_new_and_alloc (image_data_len + 1); image = gst_buffer_new_and_alloc (image_data_len + 1);
if (image == NULL) { if (image == NULL)
GST_WARNING ("failed to allocate buffer of %d for image", image_data_len); goto alloc_failed;
return NULL;
}
memcpy (GST_BUFFER_DATA (image), image_data, image_data_len); data = gst_buffer_map (image, NULL, NULL, GST_MAP_WRITE);
GST_BUFFER_DATA (image)[image_data_len] = '\0'; 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 */ /* Find GStreamer media type, can't trust declared type */
caps = gst_type_find_helper_for_buffer (NULL, image, NULL); 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 * to keep the original size of the image
*/ */
if (!g_str_equal (name, "text/uri-list")) 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) { if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
GST_LOG ("Setting image type: %d", image_type); GST_LOG ("Setting image type: %d", image_type);
@ -623,4 +622,11 @@ error:
gst_caps_unref (caps); gst_caps_unref (caps);
return NULL; return NULL;
} }
alloc_failed:
{
GST_WARNING ("failed to allocate buffer of %d for image", image_data_len);
gst_buffer_unref (image);
return NULL;
}
} }