diff options
author | Edgard Lima <edgard.lima@indt.org.br> | 2007-12-21 09:45:56 +0000 |
---|---|---|
committer | Edgard Lima <edgard.lima@indt.org.br> | 2007-12-21 09:45:56 +0000 |
commit | 0f2ac9fe8b5c7f37e61f3eef95299098ce953f1e (patch) | |
tree | 80ecd68c91efd8f1e03825664f66f7bd0d0da63e /ext/metadata | |
parent | bb4e1d10e99c206fdf0ca22a43ef20efa24236ef (diff) | |
download | gst-plugins-bad-0f2ac9fe8b5c7f37e61f3eef95299098ce953f1e.tar.gz gst-plugins-bad-0f2ac9fe8b5c7f37e61f3eef95299098ce953f1e.tar.bz2 gst-plugins-bad-0f2ac9fe8b5c7f37e61f3eef95299098ce953f1e.zip |
Removed gstmetadatacommon.
Original commit message from CVS:
Removed gstmetadatacommon.
Diffstat (limited to 'ext/metadata')
-rw-r--r-- | ext/metadata/Makefile.am | 2 | ||||
-rw-r--r-- | ext/metadata/TODO | 6 | ||||
-rw-r--r-- | ext/metadata/gstbasemetadata.c | 747 | ||||
-rw-r--r-- | ext/metadata/gstbasemetadata.h | 33 | ||||
-rw-r--r-- | ext/metadata/gstmetadatacommon.c | 630 | ||||
-rw-r--r-- | ext/metadata/gstmetadatacommon.h | 96 | ||||
-rw-r--r-- | ext/metadata/metadata.c | 78 | ||||
-rw-r--r-- | ext/metadata/metadata.h | 6 |
8 files changed, 746 insertions, 852 deletions
diff --git a/ext/metadata/Makefile.am b/ext/metadata/Makefile.am index 5123c2ae..4730d712 100644 --- a/ext/metadata/Makefile.am +++ b/ext/metadata/Makefile.am @@ -1,7 +1,6 @@ plugin_LTLIBRARIES = libgstmetadata.la libgstmetadata_la_SOURCES = gstmetadata.c \ - gstmetadatacommon.c \ gstmetadatademux.c \ metadata.c \ metadataparsejpeg.c \ @@ -25,7 +24,6 @@ libgstmetadata_la_LIBADD = $(METADATA_LIBS) -lgsttag-@GST_MAJORMINOR@ $(GST_PLUG libgstmetadata_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = gstmetadatademux.h \ - gstmetadatacommon.h \ metadata.h \ metadataparsejpeg.h \ metadatamuxjpeg.h \ diff --git a/ext/metadata/TODO b/ext/metadata/TODO index bdd228b9..1cb063ec 100644 --- a/ext/metadata/TODO +++ b/ext/metadata/TODO @@ -1,9 +1,10 @@ This file contains a list of things to be done as well some open issues (questions) related to design/implementation. +* I (Edgard Lima - alima - edgard.lima@indt.org.br) will be on vacation until 05-Jan-2008. After that I will be back on it. + TODO: -0- Remove "common" file (put inside class) 1- Add individual tags IPTC and XMP (and more for EXIF) 2- Get properties like 'width' and 'height' from caps 3- Review the code (in order to move to gst-plugins-good) @@ -16,9 +17,8 @@ OPEN ISSUES: ex: file.jpeg has XMP, then we do filesrc ! metadataparse ! jpegdec ! pngenc ! metadatamux ! files is the metadata still valid? which fields are no valid anymore? 3- Add GST_TYPE_FRACTION support for GStreamer TAGS -4- After decided issue (4) put more things to gstmetadatacommon (or else create a Class) KNOWN BUGS 1- exposure-time, exposure-program and fnumber can't be read from a file saved from scratch (whithout WHOLE_CHUNK from previous file) - + I believe it is a bu in libexif diff --git a/ext/metadata/gstbasemetadata.c b/ext/metadata/gstbasemetadata.c index 962edd3b..858145fe 100644 --- a/ext/metadata/gstbasemetadata.c +++ b/ext/metadata/gstbasemetadata.c @@ -167,6 +167,525 @@ gst_base_metadata_get_type (void) return base_metadata_type; } +/* static helper function */ + +/* + * offset - offset of buffer in original stream + * size - size of buffer + * seg_offset - offset of segment in original stream + * seg_size - size of segment + * boffset - offset inside buffer where segment starts (-1 for no intersection) + * bsize - size of intersection + * seg_binter - if segment start inside buffer is zero. if segment start before + * buffer and intersect, it is the offset inside segment. + * + * ret: + * -1 - segment before buffer + * 0 - segment intersects + * 1 - segment after buffer + */ + +static int +gst_base_metadata_get_strip_seg (const gint64 offset, guint32 size, + const gint64 seg_offset, const guint32 seg_size, + gint64 * boffset, guint32 * bsize, guint32 * seg_binter) +{ + int ret = -1; + + *boffset = -1; + *bsize = 0; + *seg_binter = -1; + + /* all segment after buffer */ + if (seg_offset >= offset + size) { + ret = 1; + goto done; + } + + if (seg_offset < offset) { + /* segment start somewhere before buffer */ + + /* all segment before buffer */ + if (seg_offset + seg_size <= offset) { + ret = -1; + goto done; + } + + *seg_binter = offset - seg_offset; + *boffset = 0; + + /* FIXME : optimize to >= size -> = size */ + if (seg_offset + seg_size >= offset + size) { + /* segment cover all buffer */ + *bsize = size; + } else { + /* segment goes from start of buffer to somewhere before end */ + *bsize = seg_size - *seg_binter; + } + + ret = 0; + + } else { + /* segment start somewhere into buffer */ + + *boffset = seg_offset - offset; + *seg_binter = 0; + + if (seg_offset + seg_size <= offset + size) { + /* all segment into buffer */ + *bsize = seg_size; + } else { + *bsize = size - *boffset; + } + + ret = 0; + + } + +done: + + return ret; + +} + +/* + * extern functions declaration + */ + +/* + +/* + * TRUE -> buffer striped or injeted + * FALSE -> buffer unmodified + */ + +gboolean +gst_base_metadata_strip_push_buffer (GstBaseMetadata * base, + gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf) +{ + MetadataChunk *strip = base->metadata->strip_chunks.chunk; + MetadataChunk *inject = base->metadata->inject_chunks.chunk; + const gsize strip_len = base->metadata->strip_chunks.len; + const gsize inject_len = base->metadata->inject_chunks.len; + + gboolean buffer_reallocated = FALSE; + + guint32 size_buf_in = GST_BUFFER_SIZE (*buf); + + gint64 *boffset_strip = NULL; + guint32 *bsize_strip = NULL; + guint32 *seg_binter_strip = NULL; + + int i, j; + gboolean need_free_strip = FALSE; + + guint32 striped_bytes = 0; + guint32 injected_bytes = 0; + + guint32 prepend_size = prepend && *prepend ? GST_BUFFER_SIZE (*prepend) : 0; + + if (inject_len) { + + for (i = 0; i < inject_len; ++i) { + int res; + + if (inject[i].offset_orig >= offset_orig) { + if (inject[i].offset_orig < offset_orig + size_buf_in) { + injected_bytes += inject[i].size; + } else { + /* segment is after size (segments are sorted) */ + break; + } + } + } + + } + + /* + * strip segments + */ + + if (strip_len == 0) + goto inject; + + if (G_UNLIKELY (strip_len > 16)) { + boffset_strip = g_new (gint64, strip_len); + bsize_strip = g_new (guint32, strip_len); + seg_binter_strip = g_new (guint32, strip_len); + need_free_strip = TRUE; + } else { + boffset_strip = g_alloca (sizeof (boffset_strip[0]) * strip_len); + bsize_strip = g_alloca (sizeof (bsize_strip[0]) * strip_len); + seg_binter_strip = g_alloca (sizeof (seg_binter_strip[0]) * strip_len); + } + + memset (bsize_strip, 0x00, sizeof (bsize_strip[0]) * strip_len); + + for (i = 0; i < strip_len; ++i) { + int res; + + res = gst_base_metadata_get_strip_seg (offset_orig, size_buf_in, + strip[i].offset_orig, strip[i].size, &boffset_strip[i], &bsize_strip[i], + &seg_binter_strip[i]); + + /* segment is after size (segments are sorted) */ + striped_bytes += bsize_strip[i]; + if (res > 0) { + break; + } + + } + + if (striped_bytes) { + + guint8 *data; + + if (!buffer_reallocated) { + buffer_reallocated = TRUE; + if (injected_bytes + prepend_size > striped_bytes) { + GstBuffer *new_buf = + gst_buffer_new_and_alloc (GST_BUFFER_SIZE (*buf) + injected_bytes + + prepend_size - striped_bytes); + + memcpy (GST_BUFFER_DATA (new_buf), GST_BUFFER_DATA (*buf), + GST_BUFFER_SIZE (*buf)); + + gst_buffer_unref (*buf); + *buf = new_buf; + + } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY)) { + GstBuffer *new_buf = gst_buffer_copy (*buf); + + gst_buffer_unref (*buf); + *buf = new_buf; + GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY); + GST_BUFFER_SIZE (*buf) += injected_bytes + prepend_size - striped_bytes; + } + } + + data = GST_BUFFER_DATA (*buf); + + striped_bytes = 0; + for (i = 0; i < strip_len; ++i) { + /* intersect */ + if (bsize_strip[i]) { + memmove (data + boffset_strip[i] - striped_bytes, + data + boffset_strip[i] + bsize_strip[i] - striped_bytes, + size_buf_in - boffset_strip[i] - bsize_strip[i]); + striped_bytes += bsize_strip[i]; + } + } + size_buf_in -= striped_bytes; + + } + +inject: + + /* + * inject segments + */ + + if (inject_len) { + + guint8 *data; + guint32 striped_so_far; + + if (!buffer_reallocated) { + buffer_reallocated = TRUE; + if (injected_bytes + prepend_size > striped_bytes) { + GstBuffer *new_buf = + gst_buffer_new_and_alloc (GST_BUFFER_SIZE (*buf) + injected_bytes + + prepend_size - striped_bytes); + + memcpy (GST_BUFFER_DATA (new_buf), GST_BUFFER_DATA (*buf), + GST_BUFFER_SIZE (*buf)); + + gst_buffer_unref (*buf); + *buf = new_buf; + + } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY)) { + GstBuffer *new_buf = gst_buffer_copy (*buf); + + gst_buffer_unref (*buf); + *buf = new_buf; + GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY); + GST_BUFFER_SIZE (*buf) += injected_bytes + prepend_size - striped_bytes; + } + } + + data = GST_BUFFER_DATA (*buf); + + injected_bytes = 0; + striped_so_far = 0; + j = 0; + for (i = 0; i < inject_len; ++i) { + int res; + + while (j < strip_len) { + if (strip[j].offset_orig < inject[i].offset_orig) + striped_so_far += bsize_strip[j++]; + else + break; + } + + if (inject[i].offset_orig >= offset_orig) { + if (inject[i].offset_orig < + offset_orig + size_buf_in + striped_bytes - injected_bytes) { + /* insert */ + guint32 buf_off = + inject[i].offset_orig - offset_orig - striped_so_far + + injected_bytes; + memmove (data + buf_off + inject[i].size, data + buf_off, + size_buf_in - buf_off); + memcpy (data + buf_off, inject[i].data, inject[i].size); + injected_bytes += inject[i].size; + size_buf_in += inject[i].size; + } else { + /* segment is after size (segments are sorted) */ + break; + } + } + } + + } + + +done: + + if (prepend_size) { + if (injected_bytes == 0 && striped_bytes == 0) { + GstBuffer *new_buf = + gst_buffer_new_and_alloc (size_buf_in + prepend_size); + + memcpy (GST_BUFFER_DATA (new_buf) + prepend_size, GST_BUFFER_DATA (*buf), + size_buf_in); + + gst_buffer_unref (*buf); + *buf = new_buf; + } else { + memmove (GST_BUFFER_DATA (*buf) + prepend_size, GST_BUFFER_DATA (*buf), + size_buf_in); + } + memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (*prepend), prepend_size); + gst_buffer_unref (*prepend); + *prepend = NULL; + } + + GST_BUFFER_SIZE (*buf) = size_buf_in + prepend_size; + + if (need_free_strip) { + g_free (boffset_strip); + g_free (bsize_strip); + g_free (seg_binter_strip); + } + + return injected_bytes || striped_bytes; + +} + +/* + * pos - position in stream striped + * orig_pos - position in original stream + * return TRUE - position in original buffer + * FALSE - position in inserted chunk + */ +gboolean +gst_base_metadata_translate_pos_to_orig (GstBaseMetadata * base, + gint64 pos, gint64 * orig_pos, GstBuffer ** buf) +{ + MetadataChunk *strip = base->metadata->strip_chunks.chunk; + MetadataChunk *inject = base->metadata->inject_chunks.chunk; + const gsize strip_len = base->metadata->strip_chunks.len; + const gsize inject_len = base->metadata->inject_chunks.len; + const gint64 duration_orig = base->duration_orig; + const gint64 duration = base->duration; + + int i; + gboolean ret = TRUE; + guint64 new_buf_size = 0; + guint64 injected_before = 0; + + if (G_UNLIKELY (pos == -1)) { + *orig_pos = -1; + return TRUE; + } else if (G_UNLIKELY (pos >= duration)) { + /* this should never happen */ + *orig_pos = duration_orig; + return TRUE; + } + + /* calculate for injected */ + + /* just calculate size */ + *orig_pos = pos; /* save pos */ + for (i = 0; i < inject_len; ++i) { + /* check if pos in inside chunk */ + if (inject[i].offset <= pos) { + if (pos < inject[i].offset + inject[i].size) { + /* orig pos points after insert chunk */ + new_buf_size += inject[i].size; + /* put pos after current chunk */ + pos = inject[i].offset + inject[i].size; + ret = FALSE; + } else { + /* in case pos is not inside a injected chunk */ + injected_before += inject[i].size; + } + } else { + break; + } + } + + /* alloc buffer and calcute original pos */ + if (buf && ret == FALSE) { + guint8 *data; + + if (*buf) + gst_buffer_unref (*buf); + *buf = gst_buffer_new_and_alloc (new_buf_size); + data = GST_BUFFER_DATA (*buf); + pos = *orig_pos; /* recover saved pos */ + for (i = 0; i < inject_len; ++i) { + if (inject[i].offset > pos) { + break; + } + if (inject[i].offset <= pos && pos < inject[i].offset + inject[i].size) { + memcpy (data, inject[i].data, inject[i].size); + data += inject[i].size; + pos = inject[i].offset + inject[i].size; + /* out position after insert chunk orig */ + *orig_pos = inject[i].offset_orig + inject[i].size; + } + } + } + + if (ret == FALSE) { + /* if it inside a injected is already done */ + goto done; + } + + /* calculate for striped */ + + *orig_pos = pos - injected_before; + for (i = 0; i < strip_len; ++i) { + if (strip[i].offset_orig > pos) { + break; + } + *orig_pos += strip[i].size; + } + +done: + + if (G_UNLIKELY (*orig_pos >= duration_orig)) { + *orig_pos = duration_orig - 1; + } + + return ret; + +} + +/* + * return: + * -1 -> error + * 0 -> succeded + * 1 -> need more data + */ + +gboolean +gst_base_metadata_calculate_offsets (GstBaseMetadata * base) +{ + int i, j; + guint32 append_size; + guint32 bytes_striped, bytes_inject; + MetadataChunk *strip = base->metadata->strip_chunks.chunk; + MetadataChunk *inject = base->metadata->inject_chunks.chunk; + gsize strip_len; + gsize inject_len; + + if (base->state != MT_STATE_PARSED) + return FALSE; + + metadata_lazy_update (base->metadata); + + strip_len = base->metadata->strip_chunks.len; + inject_len = base->metadata->inject_chunks.len; + + bytes_striped = 0; + bytes_inject = 0; + + /* calculate the new position off injected chunks */ + j = 0; + for (i = 0; i < inject_len; ++i) { + for (; j < strip_len; ++j) { + if (strip[j].offset_orig >= inject[i].offset_orig) { + break; + } + bytes_striped += strip[j].size; + } + inject[i].offset = inject[i].offset_orig - bytes_striped + bytes_inject; + bytes_inject += inject[i].size; + } + + /* calculate append (doesnt make much sense, but, anyway..) */ + append_size = 0; + for (i = inject_len - 1; i >= 0; --i) { + if (inject[i].offset_orig == base->duration_orig) + append_size += inject[i].size; + else + break; + } + if (append_size) { + guint8 *data; + + base->append_buffer = gst_buffer_new_and_alloc (append_size); + GST_BUFFER_FLAG_SET (base->append_buffer, GST_BUFFER_FLAG_READONLY); + data = GST_BUFFER_DATA (base->append_buffer); + for (i = inject_len - 1; i >= 0; --i) { + if (inject[i].offset_orig == base->duration_orig) { + memcpy (data, inject[i].data, inject[i].size); + data += inject[i].size; + } else { + break; + } + } + } + + if (base->duration_orig) { + base->duration = base->duration_orig; + for (i = 0; i < inject_len; ++i) { + base->duration += inject[i].size; + } + for (i = 0; i < strip_len; ++i) { + base->duration -= strip[i].size; + } + } + + return TRUE; + +} + +const gchar * +gst_base_metadata_get_type_name (int img_type) +{ + gchar *type_name = NULL; + + switch (img_type) { + case IMG_JPEG: + type_name = "jpeg"; + break; + case IMG_PNG: + type_name = "png"; + break; + default: + type_name = "invalid type"; + break; + } + return type_name; +} + + +/* gstreamer functions */ + static void gst_base_metadata_base_init (gpointer gclass) @@ -260,8 +779,6 @@ gst_base_metadata_init (GstBaseMetadata * filter, GstBaseMetadataClass * gclass) metadataparse_xmp_init (); /* init members */ - filter->options = META_OPT_EXIF | META_OPT_IPTC | META_OPT_XMP; - gst_base_metadata_init_members (filter); } @@ -329,7 +846,7 @@ gst_base_metadata_processing (GstBaseMetadata * filter) if (filter->need_processing) { bclass->processing (filter); - if (gst_metadata_common_calculate_offsets (&filter->common)) { + if (gst_base_metadata_calculate_offsets (filter)) { filter->need_processing = FALSE; } else { ret = FALSE; @@ -404,10 +921,10 @@ gst_base_metadata_src_event (GstPad * pad, GstEvent * event) case GST_FORMAT_BYTES: break; case GST_FORMAT_PERCENT: - if (filter->common.duration < 0) + if (filter->duration < 0) goto done; - start = start * filter->common.duration / 100; - stop = stop * filter->common.duration / 100; + start = start * filter->duration / 100; + stop = stop * filter->duration / 100; break; default: goto done; @@ -417,9 +934,9 @@ gst_base_metadata_src_event (GstPad * pad, GstEvent * event) if (start_type == GST_SEEK_TYPE_CUR) start = filter->offset + start; else if (start_type == GST_SEEK_TYPE_END) { - if (filter->common.duration < 0) + if (filter->duration < 0) goto done; - start = filter->common.duration + start; + start = filter->duration + start; } start_type == GST_SEEK_TYPE_SET; @@ -430,21 +947,20 @@ gst_base_metadata_src_event (GstPad * pad, GstEvent * event) /* FIXME: related to append */ filter->offset = start; - gst_metadata_common_translate_pos_to_orig (&filter->common, start, &start, + gst_base_metadata_translate_pos_to_orig (filter, start, &start, &filter->prepend_buffer); filter->offset_orig = start; if (stop_type == GST_SEEK_TYPE_CUR) stop = filter->offset + stop; else if (stop_type == GST_SEEK_TYPE_END) { - if (filter->common.duration < 0) + if (filter->duration < 0) goto done; - stop = filter->common.duration + stop; + stop = filter->duration + stop; } stop_type == GST_SEEK_TYPE_SET; - gst_metadata_common_translate_pos_to_orig (&filter->common, stop, &stop, - NULL); + gst_base_metadata_translate_pos_to_orig (filter, stop, &stop, NULL); gst_event_unref (event); event = gst_event_new_seek (rate, format, flags, @@ -494,7 +1010,20 @@ gst_base_metadata_finalize (GObject * object) static void gst_base_metadata_dispose_members (GstBaseMetadata * filter) { - gst_metadata_common_dispose (&filter->common); + + /* buffers used to build output buffer */ + + if (filter->prepend_buffer) { + gst_buffer_unref (filter->prepend_buffer); + filter->prepend_buffer = NULL; + } + + if (filter->append_buffer) { + gst_buffer_unref (filter->append_buffer); + filter->append_buffer = NULL; + } + + /* adapter used during parsing process */ if (filter->adapter_parsing) { gst_object_unref (filter->adapter_parsing); @@ -506,29 +1035,82 @@ gst_base_metadata_dispose_members (GstBaseMetadata * filter) filter->adapter_holding = NULL; } - if (filter->prepend_buffer) { - gst_buffer_unref (filter->prepend_buffer); - filter->prepend_buffer = NULL; - } + metadata_dispose (&filter->metadata); + } static void gst_base_metadata_init_members (GstBaseMetadata * filter) { + + filter->metadata = NULL; + + filter->img_type = IMG_NONE; + + filter->duration_orig = 0; + filter->duration = 0; + + filter->state = MT_STATE_NULL; + + filter->options = META_OPT_EXIF | META_OPT_IPTC | META_OPT_XMP; + filter->need_processing = FALSE; filter->adapter_parsing = NULL; filter->adapter_holding = NULL; filter->next_offset = 0; filter->next_size = 0; - filter->img_type = IMG_NONE; + filter->need_more_data = FALSE; filter->offset_orig = 0; filter->offset = 0; - filter->need_more_data = FALSE; + filter->append_buffer = NULL; filter->prepend_buffer = NULL; - memset (&filter->common, 0x00, sizeof (filter->common)); +} + +static void +gst_base_metadata_reset_streaming (GstBaseMetadata * filter) +{ + filter->offset_orig = 0; + filter->offset = 0; + if (filter->adapter_holding) + gst_adapter_clear (filter->adapter_holding); +} + +static void +gst_base_metadata_reset_parsing (GstBaseMetadata * filter) +{ + + + if (filter->prepend_buffer) { + gst_buffer_unref (filter->prepend_buffer); + filter->prepend_buffer = NULL; + } + + if (filter->append_buffer) { + gst_buffer_unref (filter->append_buffer); + filter->append_buffer = NULL; + } + + if (filter->adapter_parsing) + gst_adapter_clear (filter->adapter_parsing); + + if (filter->adapter_holding) + gst_adapter_clear (filter->adapter_holding); + + filter->img_type = IMG_NONE; + filter->duration_orig = 0; + filter->duration = 0; + filter->state = MT_STATE_NULL; + filter->need_processing = FALSE; + filter->next_offset = 0; + filter->next_size = 0; + filter->need_more_data = FALSE; + filter->offset_orig = 0; + filter->offset = 0; + + metadata_dispose (&filter->metadata); } @@ -617,9 +1199,8 @@ gst_base_metadata_src_query (GstPad * pad, GstQuery * query) gst_query_parse_duration (query, &format, NULL); if (format == GST_FORMAT_BYTES) { - if (filter->common.duration >= 0) { - gst_query_set_duration (query, GST_FORMAT_BYTES, - filter->common.duration); + if (filter->duration >= 0) { + gst_query_set_duration (query, GST_FORMAT_BYTES, filter->duration); ret = TRUE; } } @@ -658,11 +1239,11 @@ gst_base_metadata_parse (GstBaseMetadata * filter, const guint8 * buf, filter->next_offset = 0; filter->next_size = 0; - ret = metadata_parse (&filter->common.metadata, buf, size, + ret = metadata_parse (filter->metadata, buf, size, &filter->next_offset, &filter->next_size); if (ret == META_PARSING_ERROR) { - if (META_DATA_IMG_TYPE (filter->common.metadata) == IMG_NONE) { + if (META_DATA_IMG_TYPE (filter->metadata) == IMG_NONE) { /* image type not recognized */ GST_ELEMENT_ERROR (filter, STREAM, TYPE_NOT_FOUND, (NULL), ("Only jpeg and png are supported")); @@ -671,18 +1252,18 @@ gst_base_metadata_parse (GstBaseMetadata * filter, const guint8 * buf, } else if (ret == META_PARSING_NEED_MORE_DATA) { filter->need_more_data = TRUE; } else { - filter->common.state = MT_STATE_PARSED; + filter->state = MT_STATE_PARSED; filter->need_more_data = FALSE; filter->need_processing = TRUE; } /* reconfigure caps if it is different from type detected by 'base_metadata' function */ - if (filter->img_type != META_DATA_IMG_TYPE (filter->common.metadata)) { - filter->img_type = META_DATA_IMG_TYPE (filter->common.metadata); + if (filter->img_type != META_DATA_IMG_TYPE (filter->metadata)) { + filter->img_type = META_DATA_IMG_TYPE (filter->metadata); if (!gst_base_metadata_configure_caps (filter)) { GST_ELEMENT_ERROR (filter, STREAM, FORMAT, (NULL), ("Couldn't reconfigure caps for %s", - gst_metadata_common_get_type_name (filter->img_type))); + gst_base_metadata_get_type_name (filter->img_type))); ret = META_PARSING_ERROR; goto done; } @@ -715,8 +1296,13 @@ gst_base_metadata_chain (GstPad * pad, GstBuffer * buf) filter = GST_BASE_METADATA (gst_pad_get_parent (pad)); - if (filter->common.state != MT_STATE_PARSED) { - guint32 adpt_size = gst_adapter_available (filter->adapter_parsing); + if (filter->state != MT_STATE_PARSED) { + guint32 adpt_size; + + if (G_UNLIKELY (filter->adapter_parsing == NULL)) + filter->adapter_parsing = gst_adapter_new (); + + adpt_size = gst_adapter_available (filter->adapter_parsing); if (filter->next_offset) { if (filter->next_offset >= adpt_size) { @@ -764,7 +1350,7 @@ gst_base_metadata_chain (GstPad * pad, GstBuffer * buf) } } - if (filter->common.state == MT_STATE_PARSED) { + if (filter->state == MT_STATE_PARSED) { if (!gst_base_metadata_processing (filter)) { ret = GST_FLOW_ERROR; @@ -779,13 +1365,12 @@ gst_base_metadata_chain (GstPad * pad, GstBuffer * buf) filter->adapter_holding = NULL; } - if (filter->offset_orig + GST_BUFFER_SIZE (buf) == - filter->common.duration_orig) + if (filter->offset_orig + GST_BUFFER_SIZE (buf) == filter->duration_orig) append = TRUE; buf_size = GST_BUFFER_SIZE (buf); - gst_metadata_common_strip_push_buffer (&filter->common, filter->offset_orig, + gst_base_metadata_strip_push_buffer (filter, filter->offset_orig, &filter->prepend_buffer, &buf); if (buf) { /* may be all buffer has been striped */ @@ -800,11 +1385,11 @@ gst_base_metadata_chain (GstPad * pad, GstBuffer * buf) ret = GST_FLOW_OK; } - if (append && filter->common.append_buffer) { - gst_buffer_set_caps (filter->common.append_buffer, + if (append && filter->append_buffer) { + gst_buffer_set_caps (filter->append_buffer, GST_PAD_CAPS (filter->srcpad)); - gst_buffer_ref (filter->common.append_buffer); - ret = gst_pad_push (filter->srcpad, filter->common.append_buffer); + gst_buffer_ref (filter->append_buffer); + ret = gst_pad_push (filter->srcpad, filter->append_buffer); if (ret != GST_FLOW_OK) goto done; } @@ -852,7 +1437,7 @@ gst_base_metadata_pull_range_base (GstBaseMetadata * filter) ret = TRUE; goto done; } - filter->common.duration_orig = duration; + filter->duration_orig = duration; if (format != GST_FORMAT_BYTES) { /* this should never happen, but try chain anyway */ @@ -921,7 +1506,7 @@ gst_base_metadata_sink_activate (GstPad * pad) } /* try to base */ - if (filter->common.state == MT_STATE_NULL) { + if (filter->state == MT_STATE_NULL) { ret = gst_base_metadata_pull_range_base (filter); } @@ -968,21 +1553,20 @@ gst_base_metadata_get_range (GstPad * pad, goto done; } - if (offset + size > filter->common.duration) { - size = filter->common.duration - offset; + if (offset + size > filter->duration) { + size = filter->duration - offset; } size_orig = size; - gst_metadata_common_translate_pos_to_orig (&filter->common, offset, + gst_base_metadata_translate_pos_to_orig (filter, offset, &offset_orig, &prepend); if (size > 1) { gint64 pos; pos = offset + size - 1; - gst_metadata_common_translate_pos_to_orig (&filter->common, pos, &pos, - NULL); + gst_base_metadata_translate_pos_to_orig (filter, pos, &pos, NULL); size_orig = pos + 1 - offset_orig; } @@ -991,8 +1575,7 @@ gst_base_metadata_get_range (GstPad * pad, ret = gst_pad_pull_range (filter->sinkpad, offset_orig, size_orig, buf); if (ret == GST_FLOW_OK && *buf) { - gst_metadata_common_strip_push_buffer (&filter->common, offset_orig, - &prepend, buf); + gst_base_metadata_strip_push_buffer (filter, offset_orig, &prepend, buf); if (GST_BUFFER_SIZE (*buf) < size) { /* need append */ @@ -1008,7 +1591,7 @@ done: if (need_append) { /* FIXME: together with SEEK and - * gst_metadata_common_translate_pos_to_orig + * gst_base_metadata_translate_pos_to_orig * this way if chunk is added in the end we are in trolble * ...still not implemented 'cause it will not be the * case for the time being @@ -1029,7 +1612,7 @@ gst_base_metadata_src_activate_pull (GstPad * pad, gboolean active) ret = gst_pad_activate_pull (filter->sinkpad, active); - if (ret && filter->common.state == MT_STATE_NULL) { + if (ret && filter->state == MT_STATE_NULL) { ret = gst_base_metadata_pull_range_base (filter); } @@ -1047,9 +1630,12 @@ gst_base_metadata_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - gst_base_metadata_init_members (filter); - filter->adapter_parsing = gst_adapter_new (); - gst_metadata_common_init (&filter->common, filter->options); + gst_base_metadata_reset_parsing (filter); + metadata_init (&filter->metadata, filter->options); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (filter->metadata == NULL) + metadata_init (&filter->metadata, filter->options); break; default: break; @@ -1061,22 +1647,9 @@ gst_base_metadata_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: - filter->offset = 0; - filter->offset_orig = 0; - if (filter->adapter_parsing) { - gst_adapter_clear (filter->adapter_parsing); - } - if (filter->adapter_holding) { - gst_adapter_clear (filter->adapter_holding); - } - if (filter->common.state != MT_STATE_PARSED) { - /* cleanup parser */ - gst_metadata_common_dispose (&filter->common); - gst_metadata_common_init (&filter->common, filter->options); - } - break; - case GST_STATE_CHANGE_READY_TO_NULL: - gst_base_metadata_dispose_members (filter); + gst_base_metadata_reset_streaming (filter); + if (filter->state != MT_STATE_PARSED) + gst_base_metadata_reset_parsing (filter); break; default: break; @@ -1108,16 +1681,40 @@ gst_base_metadata_get_option_flag (const GstBaseMetadata * metadata) } void -gst_base_metadata_update_segment_with_new_buffer (GstBaseMetadata * metadata, +gst_base_metadata_update_segment_with_new_buffer (GstBaseMetadata * base, guint8 ** buf, guint32 * size, MetadataChunkType type) { - gst_metadata_common_update_segment_with_new_buffer (&metadata->common, buf, - size, type); + int i; + MetadataChunk *inject = base->metadata->inject_chunks.chunk; + const gsize inject_len = base->metadata->inject_chunks.len; + + if (!(buf && size)) + goto done; + if (*buf == 0) + goto done; + if (*size == 0) + goto done; + + for (i = 0; i < inject_len; ++i) { + if (inject[i].type == type) { + inject[i].size = *size; + if (inject[i].data) + g_free (inject[i].data); + inject[i].data = *buf; + *size = 0; + *buf = 0; + break; + } + } + +done: + + return; + } void gst_base_metadata_chunk_array_remove_zero_size (GstBaseMetadata * metadata) { - metadata_chunk_array_remove_zero_size (&metadata->common.metadata. - inject_chunks); + metadata_chunk_array_remove_zero_size (&metadata->metadata->inject_chunks); } diff --git a/ext/metadata/gstbasemetadata.h b/ext/metadata/gstbasemetadata.h index 4389cf90..cb304406 100644 --- a/ext/metadata/gstbasemetadata.h +++ b/ext/metadata/gstbasemetadata.h @@ -45,8 +45,7 @@ #define __GST_BASE_METADATA_H__ #include <gst/gst.h> - -#include "gstmetadatacommon.h" +#include "metadata.h" G_BEGIN_DECLS @@ -84,13 +83,19 @@ typedef enum _tag_BaseMetadataType { */ #define GST_BASE_METADATA_SINK_PAD(obj) (GST_BASE_METADATA_CAST (obj)->sinkpad) -#define GST_BASE_METADATA_EXIF_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->common.metadata.exif_adapter) -#define GST_BASE_METADATA_IPTC_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->common.metadata.iptc_adapter) -#define GST_BASE_METADATA_XMP_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->common.metadata.xmp_adapter) +#define GST_BASE_METADATA_EXIF_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->metadata->exif_adapter) +#define GST_BASE_METADATA_IPTC_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->metadata->iptc_adapter) +#define GST_BASE_METADATA_XMP_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->metadata->xmp_adapter) #define GST_BASE_METADATA_IMG_TYPE(obj) (GST_BASE_METADATA_CAST (obj)->img_type) +typedef enum _tag_MetadataState +{ + MT_STATE_NULL, /* still need to check media type */ + MT_STATE_PARSED +} MetadataState; + /** * GstBaseMetadata: * @element: the parent element. @@ -104,26 +109,32 @@ struct _GstBaseMetadata /*< protected >*/ GstPad *sinkpad, *srcpad; + MetaData *metadata; /* handle for parsing module */ + + ImageType img_type; + /*< private >*/ - GstMetadataCommon common; + + gint64 duration_orig; /* durarion of stream */ + gint64 duration; /* durarion of modified stream */ + + MetadataState state; MetaOptions options; - gboolean need_processing; + gboolean need_processing; /* still need some action before send first buffer */ GstAdapter *adapter_parsing; GstAdapter *adapter_holding; guint32 next_offset; guint32 next_size; - ImageType img_type; - + gboolean need_more_data; gint64 offset_orig; /* offset in original stream */ gint64 offset; /* offset in current stream */ + GstBuffer * append_buffer; GstBuffer * prepend_buffer; - gboolean need_more_data; - }; struct _GstBaseMetadataClass diff --git a/ext/metadata/gstmetadatacommon.c b/ext/metadata/gstmetadatacommon.c deleted file mode 100644 index 7fbb2cdd..00000000 --- a/ext/metadata/gstmetadatacommon.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * GStreamer - * Copyright 2007 Edgard Lima <edgard.lima@indt.org.br> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:metadatamux-metadata - * - * <refsect2> - * <title>Example launch line</title> - * <para> - * <programlisting> - * gst-launch -v -m filesrc location=./test.jpeg ! metadatamux ! fakesink silent=TRUE - * </programlisting> - * </para> - * </refsect2> - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <string.h> - -/* - * static functions declaration - */ - -#include "gstmetadatacommon.h" - -/* - * offset - offset of buffer in original stream - * size - size of buffer - * seg_offset - offset of segment in original stream - * seg_size - size of segment - * boffset - offset inside buffer where segment starts (-1 for no intersection) - * bsize - size of intersection - * seg_binter - if segment start inside buffer is zero. if segment start before - * buffer and intersect, it is the offset inside segment. - * - * ret: - * -1 - segment before buffer - * 0 - segment intersects - * 1 - segment after buffer - */ - -static int -gst_metadata_common_get_strip_seg (const gint64 offset, guint32 size, - const gint64 seg_offset, const guint32 seg_size, - gint64 * boffset, guint32 * bsize, guint32 * seg_binter) -{ - int ret = -1; - - *boffset = -1; - *bsize = 0; - *seg_binter = -1; - - /* all segment after buffer */ - if (seg_offset >= offset + size) { - ret = 1; - goto done; - } - - if (seg_offset < offset) { - /* segment start somewhere before buffer */ - - /* all segment before buffer */ - if (seg_offset + seg_size <= offset) { - ret = -1; - goto done; - } - - *seg_binter = offset - seg_offset; - *boffset = 0; - - /* FIXME : optimize to >= size -> = size */ - if (seg_offset + seg_size >= offset + size) { - /* segment cover all buffer */ - *bsize = size; - } else { - /* segment goes from start of buffer to somewhere before end */ - *bsize = seg_size - *seg_binter; - } - - ret = 0; - - } else { - /* segment start somewhere into buffer */ - - *boffset = seg_offset - offset; - *seg_binter = 0; - - if (seg_offset + seg_size <= offset + size) { - /* all segment into buffer */ - *bsize = seg_size; - } else { - *bsize = size - *boffset; - } - - ret = 0; - - } - -done: - - return ret; - -} - -/* - * extern functions declaration - */ - -void -gst_metadata_common_init (GstMetadataCommon * common, MetaOptions options) -{ - metadata_init (&common->metadata, options); -} - -void -gst_metadata_common_dispose (GstMetadataCommon * common) -{ - if (common->append_buffer) { - gst_buffer_unref (common->append_buffer); - common->append_buffer = NULL; - } - metadata_dispose (&common->metadata); -} - -/* - -/* - * TRUE -> buffer striped or injeted - * FALSE -> buffer unmodified - */ - -gboolean -gst_metadata_common_strip_push_buffer (GstMetadataCommon * common, - gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf) -{ - MetadataChunk *strip = common->metadata.strip_chunks.chunk; - MetadataChunk *inject = common->metadata.inject_chunks.chunk; - const gsize strip_len = common->metadata.strip_chunks.len; - const gsize inject_len = common->metadata.inject_chunks.len; - - gboolean buffer_reallocated = FALSE; - - guint32 size_buf_in = GST_BUFFER_SIZE (*buf); - - gint64 *boffset_strip = NULL; - guint32 *bsize_strip = NULL; - guint32 *seg_binter_strip = NULL; - - int i, j; - gboolean need_free_strip = FALSE; - - guint32 striped_bytes = 0; - guint32 injected_bytes = 0; - - guint32 prepend_size = prepend && *prepend ? GST_BUFFER_SIZE (*prepend) : 0; - - if (inject_len) { - - for (i = 0; i < inject_len; ++i) { - int res; - - if (inject[i].offset_orig >= offset_orig) { - if (inject[i].offset_orig < offset_orig + size_buf_in) { - injected_bytes += inject[i].size; - } else { - /* segment is after size (segments are sorted) */ - break; - } - } - } - - } - - /* - * strip segments - */ - - if (strip_len == 0) - goto inject; - - if (G_UNLIKELY (strip_len > 16)) { - boffset_strip = g_new (gint64, strip_len); - bsize_strip = g_new (guint32, strip_len); - seg_binter_strip = g_new (guint32, strip_len); - need_free_strip = TRUE; - } else { - boffset_strip = g_alloca (sizeof (boffset_strip[0]) * strip_len); - bsize_strip = g_alloca (sizeof (bsize_strip[0]) * strip_len); - seg_binter_strip = g_alloca (sizeof (seg_binter_strip[0]) * strip_len); - } - - memset (bsize_strip, 0x00, sizeof (bsize_strip[0]) * strip_len); - - for (i = 0; i < strip_len; ++i) { - int res; - - res = gst_metadata_common_get_strip_seg (offset_orig, size_buf_in, - strip[i].offset_orig, strip[i].size, &boffset_strip[i], &bsize_strip[i], - &seg_binter_strip[i]); - - /* segment is after size (segments are sorted) */ - striped_bytes += bsize_strip[i]; - if (res > 0) { - break; - } - - } - - if (striped_bytes) { - - guint8 *data; - - if (!buffer_reallocated) { - buffer_reallocated = TRUE; - if (injected_bytes + prepend_size > striped_bytes) { - GstBuffer *new_buf = - gst_buffer_new_and_alloc (GST_BUFFER_SIZE (*buf) + injected_bytes + - prepend_size - striped_bytes); - - memcpy (GST_BUFFER_DATA (new_buf), GST_BUFFER_DATA (*buf), - GST_BUFFER_SIZE (*buf)); - - gst_buffer_unref (*buf); - *buf = new_buf; - - } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY)) { - GstBuffer *new_buf = gst_buffer_copy (*buf); - - gst_buffer_unref (*buf); - *buf = new_buf; - GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY); - GST_BUFFER_SIZE (*buf) += injected_bytes + prepend_size - striped_bytes; - } - } - - data = GST_BUFFER_DATA (*buf); - - striped_bytes = 0; - for (i = 0; i < strip_len; ++i) { - /* intersect */ - if (bsize_strip[i]) { - memmove (data + boffset_strip[i] - striped_bytes, - data + boffset_strip[i] + bsize_strip[i] - striped_bytes, - size_buf_in - boffset_strip[i] - bsize_strip[i]); - striped_bytes += bsize_strip[i]; - } - } - size_buf_in -= striped_bytes; - - } - -inject: - - /* - * inject segments - */ - - if (inject_len) { - - guint8 *data; - guint32 striped_so_far; - - if (!buffer_reallocated) { - buffer_reallocated = TRUE; - if (injected_bytes + prepend_size > striped_bytes) { - GstBuffer *new_buf = - gst_buffer_new_and_alloc (GST_BUFFER_SIZE (*buf) + injected_bytes + - prepend_size - striped_bytes); - - memcpy (GST_BUFFER_DATA (new_buf), GST_BUFFER_DATA (*buf), - GST_BUFFER_SIZE (*buf)); - - gst_buffer_unref (*buf); - *buf = new_buf; - - } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY)) { - GstBuffer *new_buf = gst_buffer_copy (*buf); - - gst_buffer_unref (*buf); - *buf = new_buf; - GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY); - GST_BUFFER_SIZE (*buf) += injected_bytes + prepend_size - striped_bytes; - } - } - - data = GST_BUFFER_DATA (*buf); - - injected_bytes = 0; - striped_so_far = 0; - j = 0; - for (i = 0; i < inject_len; ++i) { - int res; - - while (j < strip_len) { - if (strip[j].offset_orig < inject[i].offset_orig) - striped_so_far += bsize_strip[j++]; - else - break; - } - - if (inject[i].offset_orig >= offset_orig) { - if (inject[i].offset_orig < - offset_orig + size_buf_in + striped_bytes - injected_bytes) { - /* insert */ - guint32 buf_off = - inject[i].offset_orig - offset_orig - striped_so_far + - injected_bytes; - memmove (data + buf_off + inject[i].size, data + buf_off, - size_buf_in - buf_off); - memcpy (data + buf_off, inject[i].data, inject[i].size); - injected_bytes += inject[i].size; - size_buf_in += inject[i].size; - } else { - /* segment is after size (segments are sorted) */ - break; - } - } - } - - } - - -done: - - if (prepend_size) { - if (injected_bytes == 0 && striped_bytes == 0) { - GstBuffer *new_buf = - gst_buffer_new_and_alloc (size_buf_in + prepend_size); - - memcpy (GST_BUFFER_DATA (new_buf) + prepend_size, GST_BUFFER_DATA (*buf), - size_buf_in); - - gst_buffer_unref (*buf); - *buf = new_buf; - } else { - memmove (GST_BUFFER_DATA (*buf) + prepend_size, GST_BUFFER_DATA (*buf), - size_buf_in); - } - memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (*prepend), prepend_size); - gst_buffer_unref (*prepend); - *prepend = NULL; - } - - GST_BUFFER_SIZE (*buf) = size_buf_in + prepend_size; - - if (need_free_strip) { - g_free (boffset_strip); - g_free (bsize_strip); - g_free (seg_binter_strip); - } - - return injected_bytes || striped_bytes; - -} - -/* - * pos - position in stream striped - * orig_pos - position in original stream - * return TRUE - position in original buffer - * FALSE - position in inserted chunk - */ -gboolean -gst_metadata_common_translate_pos_to_orig (GstMetadataCommon * common, - gint64 pos, gint64 * orig_pos, GstBuffer ** buf) -{ - MetadataChunk *strip = common->metadata.strip_chunks.chunk; - MetadataChunk *inject = common->metadata.inject_chunks.chunk; - const gsize strip_len = common->metadata.strip_chunks.len; - const gsize inject_len = common->metadata.inject_chunks.len; - const gint64 duration_orig = common->duration_orig; - const gint64 duration = common->duration; - - int i; - gboolean ret = TRUE; - guint64 new_buf_size = 0; - guint64 injected_before = 0; - - if (G_UNLIKELY (pos == -1)) { - *orig_pos = -1; - return TRUE; - } else if (G_UNLIKELY (pos >= duration)) { - /* this should never happen */ - *orig_pos = duration_orig; - return TRUE; - } - - /* calculate for injected */ - - /* just calculate size */ - *orig_pos = pos; /* save pos */ - for (i = 0; i < inject_len; ++i) { - /* check if pos in inside chunk */ - if (inject[i].offset <= pos) { - if (pos < inject[i].offset + inject[i].size) { - /* orig pos points after insert chunk */ - new_buf_size += inject[i].size; - /* put pos after current chunk */ - pos = inject[i].offset + inject[i].size; - ret = FALSE; - } else { - /* in case pos is not inside a injected chunk */ - injected_before += inject[i].size; - } - } else { - break; - } - } - - /* alloc buffer and calcute original pos */ - if (buf && ret == FALSE) { - guint8 *data; - - if (*buf) - gst_buffer_unref (*buf); - *buf = gst_buffer_new_and_alloc (new_buf_size); - data = GST_BUFFER_DATA (*buf); - pos = *orig_pos; /* recover saved pos */ - for (i = 0; i < inject_len; ++i) { - if (inject[i].offset > pos) { - break; - } - if (inject[i].offset <= pos && pos < inject[i].offset + inject[i].size) { - memcpy (data, inject[i].data, inject[i].size); - data += inject[i].size; - pos = inject[i].offset + inject[i].size; - /* out position after insert chunk orig */ - *orig_pos = inject[i].offset_orig + inject[i].size; - } - } - } - - if (ret == FALSE) { - /* if it inside a injected is already done */ - goto done; - } - - /* calculate for striped */ - - *orig_pos = pos - injected_before; - for (i = 0; i < strip_len; ++i) { - if (strip[i].offset_orig > pos) { - break; - } - *orig_pos += strip[i].size; - } - -done: - - if (G_UNLIKELY (*orig_pos >= duration_orig)) { - *orig_pos = duration_orig - 1; - } - - return ret; - -} - -/* - * return: - * -1 -> error - * 0 -> succeded - * 1 -> need more data - */ - -gboolean -gst_metadata_common_calculate_offsets (GstMetadataCommon * common) -{ - int i, j; - guint32 append_size; - guint32 bytes_striped, bytes_inject; - MetadataChunk *strip = common->metadata.strip_chunks.chunk; - MetadataChunk *inject = common->metadata.inject_chunks.chunk; - gsize strip_len; - gsize inject_len; - - if (common->state != MT_STATE_PARSED) - return FALSE; - - metadata_lazy_update (&common->metadata); - - strip_len = common->metadata.strip_chunks.len; - inject_len = common->metadata.inject_chunks.len; - - bytes_striped = 0; - bytes_inject = 0; - - /* calculate the new position off injected chunks */ - j = 0; - for (i = 0; i < inject_len; ++i) { - for (; j < strip_len; ++j) { - if (strip[j].offset_orig >= inject[i].offset_orig) { - break; - } - bytes_striped += strip[j].size; - } - inject[i].offset = inject[i].offset_orig - bytes_striped + bytes_inject; - bytes_inject += inject[i].size; - } - - /* calculate append (doesnt make much sense, but, anyway..) */ - append_size = 0; - for (i = inject_len - 1; i >= 0; --i) { - if (inject[i].offset_orig == common->duration_orig) - append_size += inject[i].size; - else - break; - } - if (append_size) { - guint8 *data; - - common->append_buffer = gst_buffer_new_and_alloc (append_size); - GST_BUFFER_FLAG_SET (common->append_buffer, GST_BUFFER_FLAG_READONLY); - data = GST_BUFFER_DATA (common->append_buffer); - for (i = inject_len - 1; i >= 0; --i) { - if (inject[i].offset_orig == common->duration_orig) { - memcpy (data, inject[i].data, inject[i].size); - data += inject[i].size; - } else { - break; - } - } - } - - if (common->duration_orig) { - common->duration = common->duration_orig; - for (i = 0; i < inject_len; ++i) { - common->duration += inject[i].size; - } - for (i = 0; i < strip_len; ++i) { - common->duration -= strip[i].size; - } - } - - return TRUE; - -} - -void -gst_metadata_common_update_segment_with_new_buffer (GstMetadataCommon * common, - guint8 ** buf, guint32 * size, MetadataChunkType type) -{ - int i; - MetadataChunk *inject = common->metadata.inject_chunks.chunk; - const gsize inject_len = common->metadata.inject_chunks.len; - - if (!(buf && size)) - goto done; - if (*buf == 0) - goto done; - if (*size == 0) - goto done; - - for (i = 0; i < inject_len; ++i) { - if (inject[i].type == type) { - inject[i].size = *size; - if (inject[i].data) - g_free (inject[i].data); - inject[i].data = *buf; - *size = 0; - *buf = 0; - break; - } - } - -done: - - return; - -} - -const gchar * -gst_metadata_common_get_type_name (int img_type) -{ - gchar *type_name = NULL; - - switch (img_type) { - case IMG_JPEG: - type_name = "jpeg"; - break; - case IMG_PNG: - type_name = "png"; - break; - default: - type_name = "invalid type"; - break; - } - return type_name; -} diff --git a/ext/metadata/gstmetadatacommon.h b/ext/metadata/gstmetadatacommon.h deleted file mode 100644 index 7f195dc9..00000000 --- a/ext/metadata/gstmetadatacommon.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * GStreamer - * Copyright 2007 Edgard Lima <edgard.lima@indt.org.br> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __GST_METADATA_COMMON_H__ -#define __GST_METADATA_COMMON_H__ - -#include "metadata.h" - -G_BEGIN_DECLS - -typedef struct _GstMetadataCommon GstMetadataCommon; - -typedef enum _tag_MetadataState -{ - MT_STATE_NULL, /* still need to check media type */ - MT_STATE_PARSED -} MetadataState; - -struct _GstMetadataCommon { - - MetaData metadata; - gint64 duration_orig; /* durarion of stream */ - gint64 duration; /* durarion of modified stream */ - - GstBuffer * append_buffer; - MetadataState state; - -}; - -extern void -gst_metadata_common_init(GstMetadataCommon *common, MetaOptions options); - -extern void -gst_metadata_common_dispose(GstMetadataCommon *common); - -extern gboolean -gst_metadata_common_strip_push_buffer (GstMetadataCommon *common, gint64 offset_orig, - GstBuffer ** prepend, GstBuffer ** buf); - -extern gboolean -gst_metadata_common_translate_pos_to_orig (GstMetadataCommon *common, - gint64 pos, gint64 * orig_pos, GstBuffer ** buf); - -extern gboolean -gst_metadata_common_calculate_offsets (GstMetadataCommon *common); - -extern void -gst_metadata_common_update_segment_with_new_buffer (GstMetadataCommon *common, - guint8 ** buf, guint32 * size, MetadataChunkType type); - -extern const gchar * -gst_metadata_common_get_type_name (int img_type); - -G_END_DECLS -#endif /* __GST_METADATA_COMMON_H__ */ diff --git a/ext/metadata/metadata.c b/ext/metadata/metadata.c index 8e0c06b2..fa5409ca 100644 --- a/ext/metadata/metadata.c +++ b/ext/metadata/metadata.c @@ -68,28 +68,36 @@ metadata_parse_none (MetaData * meta_data, const guint8 * buf, * Look at 'MetaOptions' to see the available options. */ void -metadata_init (MetaData * meta_data, const MetaOptions options) +metadata_init (MetaData ** meta_data, const MetaOptions options) { - meta_data->state = STATE_NULL; - meta_data->img_type = IMG_NONE; - meta_data->options = options; - meta_data->offset_orig = 0; - meta_data->exif_adapter = NULL; - meta_data->iptc_adapter = NULL; - meta_data->xmp_adapter = NULL; - if (meta_data->options & META_OPT_DEMUX) { + if (meta_data == NULL) + return; + if ((*meta_data)) + metadata_dispose (meta_data); + + (*meta_data) = g_new (MetaData, 1); + + (*meta_data)->state = STATE_NULL; + (*meta_data)->img_type = IMG_NONE; + (*meta_data)->options = options; + (*meta_data)->offset_orig = 0; + (*meta_data)->exif_adapter = NULL; + (*meta_data)->iptc_adapter = NULL; + (*meta_data)->xmp_adapter = NULL; + + if ((*meta_data)->options & META_OPT_DEMUX) { /* when parsing we will probably strip only 3 chunk (exif, iptc and xmp) so we use 4 just in case there is more than one chunk of them. But this is just for convinience, 'cause the chunk_array incriases dinamically */ - metadata_chunk_array_init (&meta_data->strip_chunks, 4); + metadata_chunk_array_init (&(*meta_data)->strip_chunks, 4); /* at most 1 chunk will be injected (JPEG JFIF) */ - metadata_chunk_array_init (&meta_data->inject_chunks, 1); + metadata_chunk_array_init (&(*meta_data)->inject_chunks, 1); } else { /* at most 1 chunk will be striped (JPEG JFIF) */ - metadata_chunk_array_init (&meta_data->strip_chunks, 1); + metadata_chunk_array_init (&(*meta_data)->strip_chunks, 1); /* at most 3 chunk will be injected (EXIF, IPTC, XMP) */ - metadata_chunk_array_init (&meta_data->inject_chunks, 3); + metadata_chunk_array_init (&(*meta_data)->inject_chunks, 3); } } @@ -99,42 +107,48 @@ metadata_init (MetaData * meta_data, const MetaOptions options) * Call this function to free any resource allocated by 'metadata_init' */ void -metadata_dispose (MetaData * meta_data) +metadata_dispose (MetaData ** meta_data) { - switch (meta_data->img_type) { + if (meta_data == NULL || (*meta_data) == NULL) + return; + + switch ((*meta_data)->img_type) { case IMG_JPEG: - if (G_LIKELY (meta_data->options & META_OPT_DEMUX)) - metadataparse_jpeg_dispose (&meta_data->format_data.jpeg_parse); + if (G_LIKELY ((*meta_data)->options & META_OPT_DEMUX)) + metadataparse_jpeg_dispose (&(*meta_data)->format_data.jpeg_parse); else - metadatamux_jpeg_dispose (&meta_data->format_data.jpeg_mux); + metadatamux_jpeg_dispose (&(*meta_data)->format_data.jpeg_mux); break; case IMG_PNG: - if (G_LIKELY (meta_data->options & META_OPT_DEMUX)) - metadataparse_png_dispose (&meta_data->format_data.png_parse); + if (G_LIKELY ((*meta_data)->options & META_OPT_DEMUX)) + metadataparse_png_dispose (&(*meta_data)->format_data.png_parse); else - metadatamux_png_dispose (&meta_data->format_data.png_mux); + metadatamux_png_dispose (&(*meta_data)->format_data.png_mux); break; } - metadata_chunk_array_free (&meta_data->strip_chunks); - metadata_chunk_array_free (&meta_data->inject_chunks); + metadata_chunk_array_free (&(*meta_data)->strip_chunks); + metadata_chunk_array_free (&(*meta_data)->inject_chunks); - if (meta_data->xmp_adapter) { - gst_object_unref (meta_data->xmp_adapter); - meta_data->xmp_adapter = NULL; + if ((*meta_data)->xmp_adapter) { + gst_object_unref ((*meta_data)->xmp_adapter); + (*meta_data)->xmp_adapter = NULL; } - if (meta_data->iptc_adapter) { - gst_object_unref (meta_data->iptc_adapter); - meta_data->iptc_adapter = NULL; + if ((*meta_data)->iptc_adapter) { + gst_object_unref ((*meta_data)->iptc_adapter); + (*meta_data)->iptc_adapter = NULL; } - if (meta_data->exif_adapter) { - gst_object_unref (meta_data->exif_adapter); - meta_data->exif_adapter = NULL; + if ((*meta_data)->exif_adapter) { + gst_object_unref ((*meta_data)->exif_adapter); + (*meta_data)->exif_adapter = NULL; } + g_free (*meta_data); + *meta_data = NULL; + } /* diff --git a/ext/metadata/metadata.h b/ext/metadata/metadata.h index 6150cc8e..63e9ec90 100644 --- a/ext/metadata/metadata.h +++ b/ext/metadata/metadata.h @@ -104,11 +104,11 @@ typedef struct _tag_MetaData } MetaData; -#define META_DATA_IMG_TYPE(p) (p).img_type +#define META_DATA_IMG_TYPE(p) (p)->img_type -extern void metadata_init (MetaData * meta_data, const MetaOptions options); +extern void metadata_init (MetaData ** meta_data, const MetaOptions options); -extern void metadata_dispose (MetaData * meta_data); +extern void metadata_dispose (MetaData ** meta_data); extern MetadataParsingReturn metadata_parse (MetaData * meta_data, const guint8 * buf, |