tag: fix writing of Exif tag payloads <= 4 bytes

When the payload for an Exif tag is less than or equal to 4 bytes,
the data is simply put into the offset field. Fix writing these
kinds of payloads on big endian systems (and possibly also on
little endian systems). The caller will have already formatted
the bytes in memory according to the writer's endianness, so just
write out the bytes as they are in this case. Fixes tags unit test
on big endian systems.
This commit is contained in:
Tim-Philipp Müller 2011-12-23 22:24:44 +00:00
parent e3c78ff661
commit dfa23662e1
2 changed files with 22 additions and 16 deletions

View file

@ -612,7 +612,7 @@ gst_tag_list_has_ifd_tags (const GstTagList * taglist,
static void
gst_exif_writer_write_tag_header (GstExifWriter * writer,
guint16 exif_tag, guint16 exif_type, guint32 count, guint32 offset,
gboolean is_data)
const guint32 * offset_data)
{
GST_DEBUG ("Writing tag entry: id %x, type %u, count %u, offset %u",
exif_tag, exif_type, count, offset);
@ -621,13 +621,17 @@ gst_exif_writer_write_tag_header (GstExifWriter * writer,
gst_byte_writer_put_uint16_le (&writer->tagwriter, exif_tag);
gst_byte_writer_put_uint16_le (&writer->tagwriter, exif_type);
gst_byte_writer_put_uint32_le (&writer->tagwriter, count);
gst_byte_writer_put_uint32_le (&writer->tagwriter, offset);
if (offset_data != NULL) {
gst_byte_writer_put_data (&writer->tagwriter, (guint8 *) offset_data, 4);
} else {
gst_byte_writer_put_uint32_le (&writer->tagwriter, offset);
}
} else if (writer->byte_order == G_BIG_ENDIAN) {
gst_byte_writer_put_uint16_be (&writer->tagwriter, exif_tag);
gst_byte_writer_put_uint16_be (&writer->tagwriter, exif_type);
gst_byte_writer_put_uint32_be (&writer->tagwriter, count);
if (is_data) {
gst_byte_writer_put_uint32_le (&writer->tagwriter, offset);
if (offset_data != NULL) {
gst_byte_writer_put_data (&writer->tagwriter, (guint8 *) offset_data, 4);
} else {
gst_byte_writer_put_uint32_be (&writer->tagwriter, offset);
}
@ -671,7 +675,7 @@ gst_exif_writer_write_rational_tag (GstExifWriter * writer,
guint32 offset = gst_byte_writer_get_size (&writer->datawriter);
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_RATIONAL,
1, offset, FALSE);
1, offset, NULL);
gst_exif_writer_write_rational_data (writer, frac_n, frac_d);
}
@ -683,7 +687,7 @@ gst_exif_writer_write_signed_rational_tag (GstExifWriter * writer,
guint32 offset = gst_byte_writer_get_size (&writer->datawriter);
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_SRATIONAL,
1, offset, FALSE);
1, offset, NULL);
gst_exif_writer_write_signed_rational_data (writer, frac_n, frac_d);
}
@ -720,7 +724,7 @@ gst_exif_writer_write_byte_tag (GstExifWriter * writer, guint16 tag,
GST_WRITE_UINT8 ((guint8 *) & offset, value);
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_BYTE,
1, offset, TRUE);
1, offset, &offset);
}
static void
@ -736,7 +740,7 @@ gst_exif_writer_write_short_tag (GstExifWriter * writer, guint16 tag,
}
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_SHORT,
1, offset, TRUE);
1, offset, &offset);
}
static void
@ -751,7 +755,7 @@ gst_exif_writer_write_long_tag (GstExifWriter * writer, guint16 tag,
}
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_LONG,
1, offset, TRUE);
1, offset, &offset);
}
@ -766,13 +770,13 @@ write_exif_undefined_tag (GstExifWriter * writer, guint16 tag,
* resulting tag headers offset and the base offset */
offset = gst_byte_writer_get_size (&writer->datawriter);
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_UNDEFINED,
size, offset, FALSE);
size, offset, NULL);
gst_byte_writer_put_data (&writer->datawriter, data, size);
} else {
/* small enough to go in the offset */
memcpy ((guint8 *) & offset, data, size);
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_UNDEFINED,
size, offset, TRUE);
size, offset, &offset);
}
}
@ -802,13 +806,13 @@ write_exif_ascii_tag (GstExifWriter * writer, guint16 tag, const gchar * str)
* resulting tag headers offset and the base offset */
offset = gst_byte_writer_get_size (&writer->datawriter);
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_ASCII,
ascii_size, offset, FALSE);
ascii_size, offset, NULL);
gst_byte_writer_put_string (&writer->datawriter, ascii_str);
} else {
/* small enough to go in the offset */
memcpy ((guint8 *) & offset, ascii_str, ascii_size);
gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_ASCII,
ascii_size, offset, TRUE);
ascii_size, offset, &offset);
}
g_free (ascii_str);
@ -1435,7 +1439,7 @@ parse_exif_rational_tag (GstExifReader * exif_reader,
}
static GstBuffer *
write_exif_ifd (const GstTagList * taglist, gboolean byte_order,
write_exif_ifd (const GstTagList * taglist, guint byte_order,
guint32 base_offset, const GstExifTagMatch * tag_map)
{
GstExifWriter writer;
@ -1492,7 +1496,7 @@ write_exif_ifd (const GstTagList * taglist, gboolean byte_order,
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_get_size (&writer.datawriter), NULL);
gst_byte_writer_put_data (&writer.datawriter,
GST_BUFFER_DATA (inner_ifd), GST_BUFFER_SIZE (inner_ifd));
gst_buffer_unref (inner_ifd);
@ -1939,7 +1943,7 @@ serialize_geo_coordinate (GstExifWriter * writer, const GstTagList * taglist,
offset = gst_byte_writer_get_size (&writer->datawriter);
gst_exif_writer_write_tag_header (writer, exiftag->exif_tag,
EXIF_TYPE_RATIONAL, 3, offset, FALSE);
EXIF_TYPE_RATIONAL, 3, offset, NULL);
gst_exif_writer_write_rational_data (writer, degrees, 1);
gst_exif_writer_write_rational_data (writer, minutes, 1);
gst_exif_writer_write_rational_data (writer, seconds, 1);

View file

@ -1392,6 +1392,7 @@ do_exif_tag_serialization_deserialization (GstTagList * taglist)
/* LE */
buf = gst_tag_list_to_exif_buffer (taglist, G_LITTLE_ENDIAN, 0);
GST_MEMDUMP ("Exif tag", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
taglist2 = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 0);
gst_buffer_unref (buf);
@ -1400,6 +1401,7 @@ do_exif_tag_serialization_deserialization (GstTagList * taglist)
/* BE */
buf = gst_tag_list_to_exif_buffer (taglist, G_BIG_ENDIAN, 0);
GST_MEMDUMP ("Exif tag", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
taglist2 = gst_tag_list_from_exif_buffer (buf, G_BIG_ENDIAN, 0);
gst_buffer_unref (buf);