mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 05:59:10 +00:00
Muxer writes (in jpeg only) whole EXIF and XMP chunks sent as tags.
Original commit message from CVS: Muxer writes (in jpeg only) whole EXIF and XMP chunks sent as tags.
This commit is contained in:
parent
ddd4af604a
commit
d5ad427c73
15 changed files with 184 additions and 174 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
||||||
|
2007-11-30 Edgard Lima <edgard.lima@indt.org.br>
|
||||||
|
|
||||||
|
* ext/metadata/gstmetadatamux.c:
|
||||||
|
* ext/metadata/gstmetadatamux.h:
|
||||||
|
* ext/metadata/gstmetadataparse.c:
|
||||||
|
* ext/metadata/gstmetadataparse.h:
|
||||||
|
* ext/metadata/metadataexif.c:
|
||||||
|
* ext/metadata/metadataexif.h:
|
||||||
|
* ext/metadata/metadataiptc.c:
|
||||||
|
* ext/metadata/metadataiptc.h:
|
||||||
|
* ext/metadata/metadatamuxjpeg.c:
|
||||||
|
* ext/metadata/metadatamuxpng.c:
|
||||||
|
* ext/metadata/metadataparsejpeg.c:
|
||||||
|
* ext/metadata/metadataparsepng.c:
|
||||||
|
* ext/metadata/metadataxmp.c:
|
||||||
|
* ext/metadata/metadataxmp.h:
|
||||||
|
Muxer writes (in jpeg only) whole EXIF and XMP chunks sent as tags.
|
||||||
|
|
||||||
2007-11-30 Thijs Vermeir <thijsvermeir@gmail.com>
|
2007-11-30 Thijs Vermeir <thijsvermeir@gmail.com>
|
||||||
|
|
||||||
* gst/librfb/rfbdecoder.c:
|
* gst/librfb/rfbdecoder.c:
|
||||||
|
|
|
@ -276,6 +276,8 @@ gst_metadata_mux_init (GstMetadataMux * filter, GstMetadataMuxClass * gclass)
|
||||||
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
|
||||||
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
||||||
|
|
||||||
|
|
||||||
|
metadataparse_xmp_init ();
|
||||||
/* init members */
|
/* init members */
|
||||||
|
|
||||||
gst_metadata_mux_init_members (filter);
|
gst_metadata_mux_init_members (filter);
|
||||||
|
@ -522,6 +524,12 @@ gst_metadata_mux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GST_EVENT_TAG:
|
case GST_EVENT_TAG:
|
||||||
|
{
|
||||||
|
GstTagList *taglist = NULL;
|
||||||
|
|
||||||
|
gst_event_parse_tag (event, &taglist);
|
||||||
|
gst_tag_list_insert (filter->taglist, taglist, GST_TAG_MERGE_REPLACE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -544,6 +552,8 @@ gst_metadata_mux_dispose (GObject * object)
|
||||||
|
|
||||||
gst_metadata_mux_dispose_members (filter);
|
gst_metadata_mux_dispose_members (filter);
|
||||||
|
|
||||||
|
metadataparse_xmp_dispose ();
|
||||||
|
|
||||||
G_OBJECT_CLASS (metadata_parent_class)->dispose (object);
|
G_OBJECT_CLASS (metadata_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,27 +763,29 @@ gst_metadata_mux_get_type_name (int img_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_metadata_update_segment (GstMetadataMux * filter, GstAdapter * adapter,
|
gst_metadata_update_segment (GstMetadataMux * filter, guint8 ** buf,
|
||||||
MetadataChunkType type)
|
guint32 * size, MetadataChunkType type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
MetadataChunk *inject = filter->mux_data.inject_chunks.chunk;
|
MetadataChunk *inject = filter->mux_data.inject_chunks.chunk;
|
||||||
const gsize inject_len = filter->mux_data.inject_chunks.len;
|
const gsize inject_len = filter->mux_data.inject_chunks.len;
|
||||||
guint32 size;
|
|
||||||
|
|
||||||
if (adapter == NULL)
|
if (!(buf && size))
|
||||||
goto done;
|
goto done;
|
||||||
|
if (*buf == 0)
|
||||||
size = gst_adapter_available (adapter);
|
goto done;
|
||||||
|
if (*size == 0)
|
||||||
if (size == 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* calculate the new position off injected chunks */
|
/* calculate the new position off injected chunks */
|
||||||
for (i = 0; i < inject_len; ++i) {
|
for (i = 0; i < inject_len; ++i) {
|
||||||
if (inject[i].type == type) {
|
if (inject[i].type == type) {
|
||||||
inject[i].size = size;
|
inject[i].size = *size;
|
||||||
inject[i].data = (guint8 *) gst_adapter_peek (adapter, inject[i].size);
|
if (inject[i].data)
|
||||||
|
g_free (inject[i].data);
|
||||||
|
inject[i].data = *buf;
|
||||||
|
*size = 0;
|
||||||
|
*buf = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -791,26 +803,22 @@ gst_metadata_create_chunks_from_tags (GstMetadataMux * filter)
|
||||||
GstMessage *msg;
|
GstMessage *msg;
|
||||||
GstTagList *taglist;
|
GstTagList *taglist;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
|
guint8 *buf = NULL;
|
||||||
|
guint32 size = 0;
|
||||||
|
|
||||||
if (META_DATA_OPTION (filter->mux_data) & META_OPT_EXIF) {
|
if (META_DATA_OPTION (filter->mux_data) & META_OPT_EXIF) {
|
||||||
metadatamux_exif_create_chunk_from_tag_list (&filter->mux_data.exif_adapter,
|
metadatamux_exif_create_chunk_from_tag_list (&buf, &size, filter->taglist);
|
||||||
filter->taglist);
|
gst_metadata_update_segment (filter, &buf, &size, MD_CHUNK_EXIF);
|
||||||
gst_metadata_update_segment (filter, filter->mux_data.exif_adapter,
|
|
||||||
MD_CHUNK_EXIF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (META_DATA_OPTION (filter->mux_data) & META_OPT_IPTC) {
|
if (META_DATA_OPTION (filter->mux_data) & META_OPT_IPTC) {
|
||||||
metadatamux_iptc_create_chunk_from_tag_list (&filter->mux_data.iptc_adapter,
|
metadatamux_iptc_create_chunk_from_tag_list (&buf, &size, filter->taglist);
|
||||||
filter->taglist);
|
gst_metadata_update_segment (filter, &buf, &size, MD_CHUNK_IPTC);
|
||||||
gst_metadata_update_segment (filter, filter->mux_data.iptc_adapter,
|
|
||||||
MD_CHUNK_IPTC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (META_DATA_OPTION (filter->mux_data) & META_OPT_XMP) {
|
if (META_DATA_OPTION (filter->mux_data) & META_OPT_XMP) {
|
||||||
metadatamux_xmp_create_chunk_from_tag_list (&filter->mux_data.xmp_adapter,
|
metadatamux_xmp_create_chunk_from_tag_list (&buf, &size, filter->taglist);
|
||||||
filter->taglist);
|
gst_metadata_update_segment (filter, &buf, &size, MD_CHUNK_XMP);
|
||||||
gst_metadata_update_segment (filter, filter->mux_data.xmp_adapter,
|
|
||||||
MD_CHUNK_XMP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata_chunk_array_remove_zero_size (&filter->mux_data.inject_chunks);
|
metadata_chunk_array_remove_zero_size (&filter->mux_data.inject_chunks);
|
||||||
|
@ -900,6 +908,8 @@ gst_metadata_mux_calculate_offsets (GstMetadataMux * filter)
|
||||||
|
|
||||||
gst_metadata_create_chunks_from_tags (filter);
|
gst_metadata_create_chunks_from_tags (filter);
|
||||||
|
|
||||||
|
metadata_lazy_update (&filter->mux_data);
|
||||||
|
|
||||||
bytes_striped = 0;
|
bytes_striped = 0;
|
||||||
bytes_inject = 0;
|
bytes_inject = 0;
|
||||||
|
|
||||||
|
@ -940,8 +950,6 @@ gst_metadata_mux_calculate_offsets (GstMetadataMux * filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata_lazy_update (&filter->mux_data);
|
|
||||||
|
|
||||||
if (filter->duration_orig) {
|
if (filter->duration_orig) {
|
||||||
filter->duration = filter->duration_orig;
|
filter->duration = filter->duration_orig;
|
||||||
for (i = 0; i < inject_len; ++i) {
|
for (i = 0; i < inject_len; ++i) {
|
||||||
|
@ -1486,7 +1494,8 @@ inject:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inject[i].offset_orig >= offset_orig) {
|
if (inject[i].offset_orig >= offset_orig) {
|
||||||
if (inject[i].offset_orig < offset_orig + size_buf_in + striped_bytes) {
|
if (inject[i].offset_orig <
|
||||||
|
offset_orig + size_buf_in + striped_bytes - injected_bytes) {
|
||||||
/* insert */
|
/* insert */
|
||||||
guint32 buf_off =
|
guint32 buf_off =
|
||||||
inject[i].offset_orig - offset_orig - striped_so_far +
|
inject[i].offset_orig - offset_orig - striped_so_far +
|
||||||
|
|
|
@ -79,7 +79,6 @@ struct _GstMetadataMux
|
||||||
gboolean iptc;
|
gboolean iptc;
|
||||||
gboolean xmp;
|
gboolean xmp;
|
||||||
|
|
||||||
GstTagList *taglist;
|
|
||||||
MetaData mux_data;
|
MetaData mux_data;
|
||||||
GstAdapter *adapter_parsing;
|
GstAdapter *adapter_parsing;
|
||||||
GstAdapter *adapter_holding;
|
GstAdapter *adapter_holding;
|
||||||
|
@ -99,7 +98,7 @@ struct _GstMetadataMux
|
||||||
|
|
||||||
gboolean need_more_data;
|
gboolean need_more_data;
|
||||||
|
|
||||||
gboolean need_send_tag; /* demux still need send tags */
|
GstTagList *taglist;
|
||||||
gboolean need_calculate_offset; /* mux need to calculate offsets of insert chunks */
|
gboolean need_calculate_offset; /* mux need to calculate offsets of insert chunks */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -280,6 +280,7 @@ gst_metadata_parse_init (GstMetadataParse * filter,
|
||||||
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
|
||||||
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
||||||
|
|
||||||
|
metadataparse_xmp_init ();
|
||||||
/* init members */
|
/* init members */
|
||||||
|
|
||||||
gst_metadata_parse_init_members (filter);
|
gst_metadata_parse_init_members (filter);
|
||||||
|
@ -548,7 +549,10 @@ gst_metadata_parse_dispose (GObject * object)
|
||||||
|
|
||||||
gst_metadata_parse_dispose_members (filter);
|
gst_metadata_parse_dispose_members (filter);
|
||||||
|
|
||||||
|
metadataparse_xmp_dispose ();
|
||||||
|
|
||||||
G_OBJECT_CLASS (metadata_parent_class)->dispose (object);
|
G_OBJECT_CLASS (metadata_parent_class)->dispose (object);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -572,11 +576,6 @@ gst_metadata_parse_dispose_members (GstMetadataParse * filter)
|
||||||
filter->adapter_holding = NULL;
|
filter->adapter_holding = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->taglist) {
|
|
||||||
gst_tag_list_free (filter->taglist);
|
|
||||||
filter->taglist = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter->append_buffer) {
|
if (filter->append_buffer) {
|
||||||
gst_buffer_unref (filter->append_buffer);
|
gst_buffer_unref (filter->append_buffer);
|
||||||
filter->append_buffer = NULL;
|
filter->append_buffer = NULL;
|
||||||
|
@ -596,7 +595,6 @@ gst_metadata_parse_init_members (GstMetadataParse * filter)
|
||||||
filter->iptc = TRUE;
|
filter->iptc = TRUE;
|
||||||
filter->xmp = TRUE;
|
filter->xmp = TRUE;
|
||||||
|
|
||||||
filter->taglist = NULL;
|
|
||||||
filter->adapter_parsing = NULL;
|
filter->adapter_parsing = NULL;
|
||||||
filter->adapter_holding = NULL;
|
filter->adapter_holding = NULL;
|
||||||
filter->next_offset = 0;
|
filter->next_offset = 0;
|
||||||
|
@ -1471,7 +1469,8 @@ inject:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inject[i].offset_orig >= offset_orig) {
|
if (inject[i].offset_orig >= offset_orig) {
|
||||||
if (inject[i].offset_orig < offset_orig + size_buf_in + striped_bytes) {
|
if (inject[i].offset_orig <
|
||||||
|
offset_orig + size_buf_in + striped_bytes - injected_bytes) {
|
||||||
/* insert */
|
/* insert */
|
||||||
guint32 buf_off =
|
guint32 buf_off =
|
||||||
inject[i].offset_orig - offset_orig - striped_so_far +
|
inject[i].offset_orig - offset_orig - striped_so_far +
|
||||||
|
@ -1734,7 +1733,6 @@ gst_metadata_parse_change_state (GstElement * element,
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||||
gst_metadata_parse_init_members (filter);
|
gst_metadata_parse_init_members (filter);
|
||||||
filter->adapter_parsing = gst_adapter_new ();
|
filter->adapter_parsing = gst_adapter_new ();
|
||||||
filter->taglist = gst_tag_list_new ();
|
|
||||||
metadata_init (&filter->parse_data, TRUE);
|
metadata_init (&filter->parse_data, TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -81,7 +81,6 @@ struct _GstMetadataParse
|
||||||
|
|
||||||
gboolean need_send_tag;
|
gboolean need_send_tag;
|
||||||
|
|
||||||
GstTagList *taglist;
|
|
||||||
MetaData parse_data;
|
MetaData parse_data;
|
||||||
GstAdapter *adapter_parsing;
|
GstAdapter *adapter_parsing;
|
||||||
GstAdapter *adapter_holding;
|
GstAdapter *adapter_holding;
|
||||||
|
|
|
@ -64,7 +64,7 @@ metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadatamux_exif_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_exif_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
|
||||||
GstTagList * taglist)
|
GstTagList * taglist)
|
||||||
{
|
{
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
|
@ -202,19 +202,46 @@ exif_content_foreach_entry_func (ExifEntry * entry, void *user_data)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
metadatamux_exif_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_exif_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
|
||||||
GstTagList * taglist)
|
GstTagList * taglist)
|
||||||
{
|
{
|
||||||
if (adapter == NULL)
|
ExifData *ed = NULL;
|
||||||
|
GstBuffer *exif_chunk = NULL;
|
||||||
|
const GValue *val = NULL;
|
||||||
|
|
||||||
|
if (!(buf && size))
|
||||||
goto done;
|
goto done;
|
||||||
|
if (*buf) {
|
||||||
|
g_free (*buf);
|
||||||
|
*buf = NULL;
|
||||||
|
}
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
if (*adapter)
|
val = gst_tag_list_get_value_index (taglist, GST_TAG_EXIF, 0);
|
||||||
g_object_unref (*adapter);
|
if (val) {
|
||||||
|
exif_chunk = gst_value_get_buffer (val);
|
||||||
|
if (exif_chunk) {
|
||||||
|
ed = exif_data_new_from_data (GST_BUFFER_DATA (exif_chunk),
|
||||||
|
GST_BUFFER_SIZE (exif_chunk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ed) {
|
||||||
|
ed = exif_data_new ();
|
||||||
|
exif_data_set_data_type (ed, EXIF_DATA_TYPE_COMPRESSED);
|
||||||
|
exif_data_fix (ed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: consider individual tags */
|
||||||
|
|
||||||
|
exif_data_save_data (ed, buf, size);
|
||||||
|
|
||||||
*adapter = gst_adapter_new ();
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
|
if (ed)
|
||||||
|
exif_data_unref (ed);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode,
|
||||||
GstAdapter * adapter, MetadataTagMapping mapping);
|
GstAdapter * adapter, MetadataTagMapping mapping);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
metadatamux_exif_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_exif_create_chunk_from_tag_list (guint8 ** buf, guint32 *size,
|
||||||
GstTagList * taglist);
|
GstTagList * taglist);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -65,7 +65,7 @@ metadataparse_iptc_tag_list_add (GstTagList * taglist, GstTagMergeMode mode,
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
metadatamux_iptc_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_iptc_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
|
||||||
GstTagList * taglist)
|
GstTagList * taglist)
|
||||||
{
|
{
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
|
@ -132,16 +132,16 @@ iptc_data_foreach_dataset_func (IptcDataSet * dataset, void *user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadatamux_iptc_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_iptc_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
|
||||||
GstTagList * taglist)
|
GstTagList * taglist)
|
||||||
{
|
{
|
||||||
if (adapter == NULL)
|
if (!(buf && size))
|
||||||
goto done;
|
goto done;
|
||||||
|
if (*buf) {
|
||||||
if (*adapter)
|
g_free (*buf);
|
||||||
g_object_unref (*adapter);
|
*buf = NULL;
|
||||||
|
}
|
||||||
*adapter = gst_adapter_new ();
|
*size = 0;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ metadataparse_iptc_tag_list_add (GstTagList * taglist, GstTagMergeMode mode,
|
||||||
GstAdapter * adapter, MetadataTagMapping mapping);
|
GstAdapter * adapter, MetadataTagMapping mapping);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
metadatamux_iptc_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_iptc_create_chunk_from_tag_list (guint8 ** buf, guint32 *size,
|
||||||
GstTagList * taglist);
|
GstTagList * taglist);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -54,16 +54,49 @@ metadatamux_jpeg_reading (JpegMuxData * jpeg_data, guint8 ** buf,
|
||||||
|
|
||||||
#define READ(buf, size) ( (size)--, *((buf)++) )
|
#define READ(buf, size) ( (size)--, *((buf)++) )
|
||||||
|
|
||||||
|
static void
|
||||||
|
metadatamux_wrap_chunk (MetadataChunk * chunk, guint8 * buf, guint32 buf_size,
|
||||||
|
guint8 a, guint8 b)
|
||||||
|
{
|
||||||
|
guint8 *data = g_new (guint8, 4 + buf_size + chunk->size);
|
||||||
|
|
||||||
|
memcpy (data + 4 + buf_size, chunk->data, chunk->size);
|
||||||
|
g_free (chunk->data);
|
||||||
|
chunk->data = data;
|
||||||
|
chunk->size += 4 + buf_size;
|
||||||
|
data[0] = a;
|
||||||
|
data[1] = b;
|
||||||
|
data[2] = (chunk->size - 2) >> 8;
|
||||||
|
data[3] = (chunk->size - 2) & 0x00FF;
|
||||||
|
if (buf && buf_size) {
|
||||||
|
memcpy (data + 4, buf, buf_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadatamux_jpeg_lazy_update (JpegMuxData * jpeg_data)
|
metadatamux_jpeg_lazy_update (JpegMuxData * jpeg_data)
|
||||||
{
|
{
|
||||||
gsize i;
|
gsize i;
|
||||||
|
|
||||||
for (i = 0; i < jpeg_data->inject_chunks->len; ++i) {
|
for (i = 0; i < jpeg_data->inject_chunks->len; ++i) {
|
||||||
if (jpeg_data->inject_chunks->chunk[i].type == MD_CHUNK_EXIF &&
|
if (jpeg_data->inject_chunks->chunk[i].size > 0 &&
|
||||||
jpeg_data->inject_chunks->chunk[i].size > 0) {
|
jpeg_data->inject_chunks->chunk[i].data) {
|
||||||
/* zero size chunks should be removed before but we check anyway */
|
switch (jpeg_data->inject_chunks->chunk[i].type) {
|
||||||
break;
|
case MD_CHUNK_EXIF:
|
||||||
|
metadatamux_wrap_chunk (&jpeg_data->inject_chunks->chunk[i], NULL, 0,
|
||||||
|
0xFF, 0xE1);
|
||||||
|
break;
|
||||||
|
case MD_CHUNK_XMP:
|
||||||
|
{
|
||||||
|
static const char XmpHeader[] = "http://ns.adobe.com/xap/1.0/";
|
||||||
|
|
||||||
|
metadatamux_wrap_chunk (&jpeg_data->inject_chunks->chunk[i],
|
||||||
|
XmpHeader, sizeof (XmpHeader), 0xFF, 0xE1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i == jpeg_data->inject_chunks->len) {
|
if (i == jpeg_data->inject_chunks->len) {
|
||||||
|
@ -181,21 +214,6 @@ metadatamux_jpeg_reading (JpegMuxData * jpeg_data, guint8 ** buf,
|
||||||
mark[1] = READ (*buf, *bufsize);
|
mark[1] = READ (*buf, *bufsize);
|
||||||
|
|
||||||
if (mark[0] == 0xFF) {
|
if (mark[0] == 0xFF) {
|
||||||
if (mark[1] == 0xD9) { /* end of image */
|
|
||||||
ret = 0;
|
|
||||||
jpeg_data->state = JPEG_MUX_DONE;
|
|
||||||
goto done;
|
|
||||||
} else if (mark[1] == 0xDA) { /* start of scan, lets not look behinf of this */
|
|
||||||
ret = 0;
|
|
||||||
jpeg_data->state = JPEG_MUX_DONE;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*bufsize < 2) {
|
|
||||||
*next_size = (*buf - *next_start) + 2;
|
|
||||||
ret = 1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk_size = READ (*buf, *bufsize) << 8;
|
chunk_size = READ (*buf, *bufsize) << 8;
|
||||||
chunk_size += READ (*buf, *bufsize);
|
chunk_size += READ (*buf, *bufsize);
|
||||||
|
@ -203,27 +221,32 @@ metadatamux_jpeg_reading (JpegMuxData * jpeg_data, guint8 ** buf,
|
||||||
if (mark[1] == 0xE0) { /* may be JFIF */
|
if (mark[1] == 0xE0) { /* may be JFIF */
|
||||||
|
|
||||||
if (chunk_size >= 16) {
|
if (chunk_size >= 16) {
|
||||||
if (*bufsize < 14) {
|
if (*bufsize < 5) {
|
||||||
*next_size = (*buf - *next_start) + 14;
|
*next_size = (*buf - *next_start) + 5;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == memcmp (JfifHeader, *buf, 5)) {
|
if (0 == memcmp (JfifHeader, *buf, 5)) {
|
||||||
jfif_found = TRUE;
|
jfif_found = TRUE;
|
||||||
/* FIXME: should we fail if not find JFIF */
|
|
||||||
/* Yes, I think so */
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* FIXME: should we check if the first chunk is EXIF? */
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_chunk_offset = (*buf - step_buf) + offset - 4; /* maker + size */
|
if (!jfif_found) {
|
||||||
|
ret = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_chunk_offset = 2;
|
||||||
|
|
||||||
/* EXIF will always be in the begining */
|
/* EXIF will always be in the begining */
|
||||||
|
|
||||||
memset (&chunk, 0x00, sizeof (MetadataChunk));
|
memset (&chunk, 0x00, sizeof (MetadataChunk));
|
||||||
chunk.offset_orig = new_chunk_offset;
|
chunk.offset_orig = 2;
|
||||||
chunk.type = MD_CHUNK_EXIF;
|
chunk.type = MD_CHUNK_EXIF;
|
||||||
metadata_chunk_array_append_sorted (jpeg_data->inject_chunks, &chunk);
|
metadata_chunk_array_append_sorted (jpeg_data->inject_chunks, &chunk);
|
||||||
|
|
||||||
|
@ -232,7 +255,7 @@ metadatamux_jpeg_reading (JpegMuxData * jpeg_data, guint8 ** buf,
|
||||||
/* this acation can be canceled with lazy update if no Exif is add */
|
/* this acation can be canceled with lazy update if no Exif is add */
|
||||||
|
|
||||||
memset (&chunk, 0x00, sizeof (MetadataChunk));
|
memset (&chunk, 0x00, sizeof (MetadataChunk));
|
||||||
chunk.offset_orig = new_chunk_offset;
|
chunk.offset_orig = 2;
|
||||||
chunk.size = chunk_size + 2; /* chunk size plus app marker */
|
chunk.size = chunk_size + 2; /* chunk size plus app marker */
|
||||||
chunk.type = MD_CHUNK_UNKNOWN;
|
chunk.type = MD_CHUNK_UNKNOWN;
|
||||||
|
|
||||||
|
|
|
@ -50,14 +50,6 @@ metadatamux_png_reading (PngMuxData * png_data, guint8 ** buf,
|
||||||
guint32 * bufsize, const guint32 offset, const guint8 * step_buf,
|
guint32 * bufsize, const guint32 offset, const guint8 * step_buf,
|
||||||
guint8 ** next_start, guint32 * next_size);
|
guint8 ** next_start, guint32 * next_size);
|
||||||
|
|
||||||
static int
|
|
||||||
metadatamux_png_xmp (PngMuxData * png_data, guint8 ** buf,
|
|
||||||
guint32 * bufsize, guint8 ** next_start, guint32 * next_size);
|
|
||||||
|
|
||||||
static int
|
|
||||||
metadatamux_png_jump (PngMuxData * png_data, guint8 ** buf,
|
|
||||||
guint32 * bufsize, guint8 ** next_start, guint32 * next_size);
|
|
||||||
|
|
||||||
#define READ(buf, size) ( (size)--, *((buf)++) )
|
#define READ(buf, size) ( (size)--, *((buf)++) )
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -78,14 +70,11 @@ metadatamux_png_init (PngMuxData * png_data, GstAdapter ** exif_adpt,
|
||||||
png_data->strip_chunks = strip_chunks;
|
png_data->strip_chunks = strip_chunks;
|
||||||
png_data->inject_chunks = inject_chunks;
|
png_data->inject_chunks = inject_chunks;
|
||||||
|
|
||||||
metadataparse_xmp_init ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadatamux_png_dispose (PngMuxData * png_data)
|
metadatamux_png_dispose (PngMuxData * png_data)
|
||||||
{
|
{
|
||||||
metadataparse_xmp_dispose ();
|
|
||||||
|
|
||||||
png_data->xmp_adapter = NULL;
|
png_data->xmp_adapter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,16 +128,6 @@ metadatamux_png_parse (PngMuxData * png_data, guint8 * buf,
|
||||||
metadatamux_png_reading (png_data, &buf, bufsize,
|
metadatamux_png_reading (png_data, &buf, bufsize,
|
||||||
offset, step_buf, next_start, next_size);
|
offset, step_buf, next_start, next_size);
|
||||||
break;
|
break;
|
||||||
case PNG_MUX_JUMPING:
|
|
||||||
ret =
|
|
||||||
metadatamux_png_jump (png_data, &buf, bufsize, next_start,
|
|
||||||
next_size);
|
|
||||||
break;
|
|
||||||
case PNG_MUX_XMP:
|
|
||||||
ret =
|
|
||||||
metadatamux_png_xmp (png_data, &buf, bufsize, next_start,
|
|
||||||
next_size);
|
|
||||||
break;
|
|
||||||
case PNG_MUX_DONE:
|
case PNG_MUX_DONE:
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
|
@ -175,6 +154,7 @@ metadatamux_png_reading (PngMuxData * png_data, guint8 ** buf,
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
guint8 mark[4];
|
guint8 mark[4];
|
||||||
guint32 chunk_size = 0;
|
guint32 chunk_size = 0;
|
||||||
|
MetadataChunk chunk;
|
||||||
|
|
||||||
static const char XmpHeader[] = "XML:com.adobe.xmp";
|
static const char XmpHeader[] = "XML:com.adobe.xmp";
|
||||||
|
|
||||||
|
@ -196,45 +176,22 @@ metadatamux_png_reading (PngMuxData * png_data, guint8 ** buf,
|
||||||
mark[2] = READ (*buf, *bufsize);
|
mark[2] = READ (*buf, *bufsize);
|
||||||
mark[3] = READ (*buf, *bufsize);
|
mark[3] = READ (*buf, *bufsize);
|
||||||
|
|
||||||
if (mark[0] == 'I' && mark[1] == 'E' && mark[2] == 'N' && mark[3] == 'D') {
|
if (!(mark[0] == 'I' && mark[1] == 'H' && mark[2] == 'D' && mark[3] == 'R')) {
|
||||||
ret = 0;
|
ret = -1;
|
||||||
png_data->state = PNG_MUX_DONE;
|
png_data->state = PNG_MUX_NULL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mark[0] == 'i' && mark[1] == 'T' && mark[2] == 'X' && mark[3] == 't') {
|
/* always inject after first chunk (IHDR) */
|
||||||
if (chunk_size >= 22) { /* "XML:com.adobe.xmp" plus some flags */
|
|
||||||
if (*bufsize < 22) {
|
|
||||||
*next_size = (*buf - *next_start) + 22;
|
|
||||||
ret = 1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == memcmp (XmpHeader, *buf, 18)) {
|
memset (&chunk, 0x00, sizeof (MetadataChunk));
|
||||||
MetadataChunk chunk;
|
/* 8(header) + 4(size) +4(id) + chunksize + 4(crc) */
|
||||||
|
chunk.offset_orig = chunk_size + 20;
|
||||||
|
chunk.type = MD_CHUNK_XMP;
|
||||||
|
|
||||||
memset (&chunk, 0x00, sizeof (MetadataChunk));
|
metadata_chunk_array_append_sorted (png_data->inject_chunks, &chunk);
|
||||||
chunk.offset_orig = (*buf - step_buf) + offset - 8; /* maker + size */
|
|
||||||
chunk.size = chunk_size + 12; /* chunk size plus app marker plus crc */
|
|
||||||
|
|
||||||
metadata_chunk_array_append_sorted (png_data->strip_chunks, &chunk);
|
png_data->state = PNG_MUX_DONE;
|
||||||
|
|
||||||
/* if adapter has been provided, prepare to hold chunk */
|
|
||||||
if (png_data->xmp_adapter) {
|
|
||||||
*buf += 22; /* jump "XML:com.adobe.xmp" plus some flags */
|
|
||||||
*bufsize -= 22;
|
|
||||||
png_data->read = chunk_size - 22; /* four CRC bytes at the end will be jumped after */
|
|
||||||
png_data->state = PNG_MUX_XMP;
|
|
||||||
ret = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* just set jump sise */
|
|
||||||
png_data->read = chunk_size + 4; /* four CRC bytes at the end */
|
|
||||||
png_data->state = PNG_MUX_JUMPING;
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -243,31 +200,3 @@ done:
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
metadatamux_png_jump (PngMuxData * png_data, guint8 ** buf,
|
|
||||||
guint32 * bufsize, guint8 ** next_start, guint32 * next_size)
|
|
||||||
{
|
|
||||||
png_data->state = PNG_MUX_READING;
|
|
||||||
return metadataparse_util_jump_chunk (&png_data->read, buf,
|
|
||||||
bufsize, next_start, next_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
metadatamux_png_xmp (PngMuxData * png_data, guint8 ** buf,
|
|
||||||
guint32 * bufsize, guint8 ** next_start, guint32 * next_size)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = metadataparse_util_hold_chunk (&png_data->read, buf,
|
|
||||||
bufsize, next_start, next_size, png_data->xmp_adapter);
|
|
||||||
if (ret == 0) {
|
|
||||||
/* jump four CRC bytes at the end of chunk */
|
|
||||||
png_data->read = 4;
|
|
||||||
png_data->state = PNG_MUX_JUMPING;
|
|
||||||
/* if there is a second XMP chunk in the file it will be jumped */
|
|
||||||
png_data->xmp_adapter = NULL;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -91,14 +91,11 @@ metadataparse_jpeg_init (JpegParseData * jpeg_data, GstAdapter ** exif_adpt,
|
||||||
jpeg_data->strip_chunks = strip_chunks;
|
jpeg_data->strip_chunks = strip_chunks;
|
||||||
jpeg_data->inject_chunks = inject_chunks;
|
jpeg_data->inject_chunks = inject_chunks;
|
||||||
|
|
||||||
metadataparse_xmp_init ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadataparse_jpeg_dispose (JpegParseData * jpeg_data)
|
metadataparse_jpeg_dispose (JpegParseData * jpeg_data)
|
||||||
{
|
{
|
||||||
metadataparse_xmp_dispose ();
|
|
||||||
|
|
||||||
jpeg_data->exif_adapter = NULL;
|
jpeg_data->exif_adapter = NULL;
|
||||||
jpeg_data->iptc_adapter = NULL;
|
jpeg_data->iptc_adapter = NULL;
|
||||||
jpeg_data->xmp_adapter = NULL;
|
jpeg_data->xmp_adapter = NULL;
|
||||||
|
|
|
@ -78,14 +78,11 @@ metadataparse_png_init (PngParseData * png_data, GstAdapter ** exif_adpt,
|
||||||
png_data->strip_chunks = strip_chunks;
|
png_data->strip_chunks = strip_chunks;
|
||||||
png_data->inject_chunks = inject_chunks;
|
png_data->inject_chunks = inject_chunks;
|
||||||
|
|
||||||
metadataparse_xmp_init ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadataparse_png_dispose (PngParseData * png_data)
|
metadataparse_png_dispose (PngParseData * png_data)
|
||||||
{
|
{
|
||||||
metadataparse_xmp_dispose ();
|
|
||||||
|
|
||||||
png_data->xmp_adapter = NULL;
|
png_data->xmp_adapter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +210,7 @@ metadataparse_png_reading (PngParseData * png_data, guint8 ** buf,
|
||||||
memset (&chunk, 0x00, sizeof (MetadataChunk));
|
memset (&chunk, 0x00, sizeof (MetadataChunk));
|
||||||
chunk.offset_orig = (*buf - step_buf) + offset - 8; /* maker + size */
|
chunk.offset_orig = (*buf - step_buf) + offset - 8; /* maker + size */
|
||||||
chunk.size = chunk_size + 12; /* chunk size plus app marker plus crc */
|
chunk.size = chunk_size + 12; /* chunk size plus app marker plus crc */
|
||||||
|
chunk.type = MD_CHUNK_XMP;
|
||||||
|
|
||||||
metadata_chunk_array_append_sorted (png_data->strip_chunks, &chunk);
|
metadata_chunk_array_append_sorted (png_data->strip_chunks, &chunk);
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ metadataparse_xmp_dispose (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadatamux_xmp_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_xmp_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
|
||||||
GstTagList * taglist)
|
GstTagList * taglist)
|
||||||
{
|
{
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
|
@ -247,16 +247,29 @@ metadataparse_xmp_iter (XmpPtr xmp, XmpIteratorPtr iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadatamux_xmp_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_xmp_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
|
||||||
GstTagList * taglist)
|
GstTagList * taglist)
|
||||||
{
|
{
|
||||||
if (adapter == NULL)
|
GstBuffer *xmp_chunk = NULL;
|
||||||
|
const GValue *val = NULL;
|
||||||
|
|
||||||
|
if (!(buf && size))
|
||||||
goto done;
|
goto done;
|
||||||
|
if (*buf) {
|
||||||
|
g_free (*buf);
|
||||||
|
*buf = NULL;
|
||||||
|
}
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
if (*adapter)
|
val = gst_tag_list_get_value_index (taglist, GST_TAG_XMP, 0);
|
||||||
g_object_unref (*adapter);
|
if (val) {
|
||||||
|
xmp_chunk = gst_value_get_buffer (val);
|
||||||
*adapter = gst_adapter_new ();
|
if (xmp_chunk) {
|
||||||
|
*size = GST_BUFFER_SIZE (xmp_chunk);
|
||||||
|
*buf = g_new (guint8, *size);
|
||||||
|
memcpy (*buf, GST_BUFFER_DATA (xmp_chunk), *size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ extern gboolean metadataparse_xmp_init (void);
|
||||||
extern void metadataparse_xmp_dispose (void);
|
extern void metadataparse_xmp_dispose (void);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
metadatamux_xmp_create_chunk_from_tag_list (GstAdapter ** adapter,
|
metadatamux_xmp_create_chunk_from_tag_list (guint8 ** buf, guint32 *size,
|
||||||
GstTagList * taglist);
|
GstTagList * taglist);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
Loading…
Reference in a new issue