From f0f6c96a9204419c429c38915d9340d092b570c4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Apr 2018 16:44:48 +0200 Subject: BLI_string: macros that de-duplicate sizeof arg --- source/blender/blenlib/BLI_string.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index d137806c575..48be9d1842f 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -103,6 +103,20 @@ int BLI_string_find_split_words( const char delim, int r_words[][2], int words_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +/** \name String Copy/Format Macros + * Avoid repeating destination with `sizeof(..)`. + * \note `ARRAY_SIZE` allows pointers on some platforms. + * \{ */ +#define STRNCPY(dst, src) \ + BLI_strncpy(dst, src, ARRAY_SIZE(dst)) +#define STRNCPY_RLEN(dst, src) \ + BLI_strncpy_rlen(dst, src, ARRAY_SIZE(dst)) +#define SNPRINTF(dst, format, ...) \ + BLI_snprintf(dst, ARRAY_SIZE(dst), format, __VA_ARGS__) +#define SNPRINTF_RLEN(dst, format, ...) \ + BLI_snprintf_rlen(dst, ARRAY_SIZE(dst), format, __VA_ARGS__) +/** \} */ + #ifdef __cplusplus } #endif -- cgit v1.2.3 From b0a767b85b0acacc40a414dd3f961b206a6b22f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 5 Apr 2018 16:27:15 +0200 Subject: IMB_metadata improvements - Metadata handling is now separate from `ImBuf *`, allowing it to be used with a generic `IDProperty *`. - Merged `IMB_metadata_add_field()` and `IMB_metadata_change_field()` into a more robust `IMB_metadata_set_field()`. This new function doesn't return any status (it now always succeeds, and the previously existing return value was never checked anyway). - Removed `IMB_metadata_del_field()` as it was never actually used anywhere. - Use `IMB_metadata_ensure()` instead of having `IMB_metadata_set_field()` create the containing `IDProperty` for you. - Deduplicated function declarations, moved `intern/IMB_metadata.h` out of `intern/`. Note that this does mean that we have some extra `#include "IMB_metadata.h"` lines now, as the metadata functions are no longer declared in `IMB_imbuf.h`. - Deduplicated function declarations, all metadata-related declarations are now in imbuf/IMB_metadata.h. Part of: https://developer.blender.org/D2273 Reviewed by: @campbellbarton --- source/blender/blenkernel/intern/image.c | 17 ++-- source/blender/blenkernel/intern/seqeffects.c | 1 + source/blender/blenkernel/intern/sequencer.c | 1 + source/blender/editors/screen/area.c | 3 +- source/blender/imbuf/CMakeLists.txt | 2 +- source/blender/imbuf/IMB_imbuf.h | 16 ---- source/blender/imbuf/IMB_metadata.h | 77 ++++++++++++++++++ source/blender/imbuf/intern/IMB_metadata.h | 66 ---------------- source/blender/imbuf/intern/allocimbuf.c | 2 +- source/blender/imbuf/intern/colormanagement.c | 1 + source/blender/imbuf/intern/jpeg.c | 6 +- source/blender/imbuf/intern/metadata.c | 90 ++++++++-------------- .../blender/imbuf/intern/openexr/openexr_api.cpp | 3 +- source/blender/imbuf/intern/png.c | 3 +- source/blender/imbuf/intern/thumbs.c | 19 ++--- source/blender/render/intern/source/pipeline.c | 1 + 16 files changed, 145 insertions(+), 163 deletions(-) create mode 100644 source/blender/imbuf/IMB_metadata.h delete mode 100644 source/blender/imbuf/intern/IMB_metadata.h (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f0b9afa15fa..e65692fb1b4 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -46,6 +46,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_moviecache.h" +#include "IMB_metadata.h" #ifdef WITH_OPENEXR # include "intern/openexr/openexr_multi.h" @@ -2172,27 +2173,31 @@ void BKE_stamp_data_free(struct StampData *stamp_data) } /* wrap for callback only */ -static void metadata_change_field(void *data, const char *propname, char *propvalue, int UNUSED(len)) +static void metadata_set_field(void *data, const char *propname, char *propvalue, int UNUSED(len)) { - IMB_metadata_change_field(data, propname, propvalue); + /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */ + struct ImBuf *imbuf = data; + IMB_metadata_set_field(imbuf->metadata, propname, propvalue); } static void metadata_get_field(void *data, const char *propname, char *propvalue, int len) { - IMB_metadata_get_field(data, propname, propvalue, len); + /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */ + struct ImBuf *imbuf = data; + IMB_metadata_get_field(imbuf->metadata, propname, propvalue, len); } void BKE_imbuf_stamp_info(RenderResult *rr, struct ImBuf *ibuf) { struct StampData *stamp_data = rr->stamp_data; - - BKE_stamp_info_callback(ibuf, stamp_data, metadata_change_field, false); + IMB_metadata_ensure(&ibuf->metadata); + BKE_stamp_info_callback(ibuf, stamp_data, metadata_set_field, false); } void BKE_stamp_info_from_imbuf(RenderResult *rr, struct ImBuf *ibuf) { struct StampData *stamp_data = rr->stamp_data; - + IMB_metadata_ensure(&ibuf->metadata); BKE_stamp_info_callback(ibuf, stamp_data, metadata_get_field, true); } diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index ee80438db64..49f120de250 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -52,6 +52,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_colormanagement.h" +#include "IMB_metadata.h" #include "BLI_math_color_blend.h" diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 095a8621191..1e61ff526ef 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -84,6 +84,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_colormanagement.h" +#include "IMB_metadata.h" #include "BKE_context.h" #include "BKE_sound.h" diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index fc0922c7b7c..caae803100b 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -63,6 +63,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_metadata.h" #include "UI_interface.h" #include "UI_interface_icons.h" @@ -2138,7 +2139,7 @@ static const char *meta_data_list[] = BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset) { - return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]); + return (IMB_metadata_get_field(ibuf->metadata, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]); } static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const bool is_top) diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index c3950d8eb83..e73f227dec8 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -73,6 +73,7 @@ set(SRC IMB_colormanagement.h IMB_imbuf.h IMB_imbuf_types.h + IMB_metadata.h IMB_moviecache.h IMB_thumbs.h intern/IMB_allocimbuf.h @@ -81,7 +82,6 @@ set(SRC intern/IMB_filetype.h intern/IMB_filter.h intern/IMB_indexer.h - intern/IMB_metadata.h intern/imbuf.h # orphan include diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index a0fc273a746..e5cd21a3248 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -566,22 +566,6 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, const float col[4], struct ColorManagedDisplay *display, int x1, int y1, int x2, int y2); -/** - * - * \attention Defined in metadata.c - */ -/** read the field from the image info into the field - * \param img - the ImBuf that contains the image data - * \param key - the key of the field - * \param value - the data in the field, first one found with key is returned, - * memory has to be allocated by user. - * \param len - length of value buffer allocated by user. - * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise - */ -bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len); -bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field); -void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb); - /* exported for image tools in blender, to quickly allocate 32 bits rect */ void *imb_alloc_pixels(unsigned int x, unsigned int y, diff --git a/source/blender/imbuf/IMB_metadata.h b/source/blender/imbuf/IMB_metadata.h new file mode 100644 index 00000000000..258d6bb1c5a --- /dev/null +++ b/source/blender/imbuf/IMB_metadata.h @@ -0,0 +1,77 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Austin Benesh. Ton Roosendaal. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/imbuf/intern/IMB_metadata.h + * \ingroup imbuf + */ + + +#ifndef __IMB_METADATA_H__ +#define __IMB_METADATA_H__ + +struct anim; +struct ImBuf; +struct IDProperty; + +/** The metadata is a list of key/value pairs (both char *) that can me + * saved in the header of several image formats. + * Apart from some common keys like + * 'Software' and 'Description' (png standard) we'll use keys within the + * Blender namespace, so should be called 'Blender::StampInfo' or 'Blender::FrameNum' + * etc... + * + * The keys & values are stored in ID properties, in the group "metadata". + */ + +/** Ensure that the metadata property is a valid IDProperty object. + * This is a no-op when *metadata != NULL. + */ +void IMB_metadata_ensure(struct IDProperty **metadata); +void IMB_metadata_free(struct IDProperty *metadata); + +/** Read the field from the image info into the field. + * \param metadata - the IDProperty that contains the metadata + * \param key - the key of the field + * \param value - the data in the field, first one found with key is returned, + * memory has to be allocated by user. + * \param len - length of value buffer allocated by user. + * \return - 1 (true) if metadata is present and value for the key found, 0 (false) otherwise + */ +bool IMB_metadata_get_field(struct IDProperty *metadata, const char *key, char *value, const size_t len); + +/** Set user data in the metadata. + * If the field already exists its value is overwritten, otherwise the field + * will be added with the given value. + * \param metadata - the IDProperty that contains the metadata + * \param key - the key of the field + * \param value - the data to be written to the field. zero terminated string + */ +void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value); + +void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb); + +#endif /* __IMB_METADATA_H__ */ diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h deleted file mode 100644 index bc0b2c70ecb..00000000000 --- a/source/blender/imbuf/intern/IMB_metadata.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Austin Benesh. Ton Roosendaal. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/imbuf/intern/IMB_metadata.h - * \ingroup imbuf - */ - - -#ifndef __IMB_METADATA_H__ -#define __IMB_METADATA_H__ - -struct ImBuf; - -/** The metadata is a list of key/value pairs (both char *) that can me - * saved in the header of several image formats. - * Apart from some common keys like - * 'Software' and 'Description' (png standard) we'll use keys within the - * Blender namespace, so should be called 'Blender::StampInfo' or 'Blender::FrameNum' - * etc... - */ - - -/* free blender ImMetaData struct */ -void IMB_metadata_free(struct ImBuf *img); - -/** set user data in the ImMetaData struct, which has to be allocated with IMB_metadata_create - * before calling this function. - * \param img - the ImBuf that contains the image data - * \param key - the key of the field - * \param value - the data to be written to the field. zero terminated string - * \return - 1 (true) if ImageInfo present, 0 (false) otherwise - */ -bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value); - -/** delete the key/field par in the ImMetaData struct. - * \param img - the ImBuf that contains the image data - * \param key - the key of the field - * \return - 1 (true) if delete the key/field, 0 (false) otherwise - */ -bool IMB_metadata_del_field(struct ImBuf *img, const char *key); - -#endif /* __IMB_METADATA_H__ */ diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 7fc4a65d8d7..faa0b5f7b6e 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -219,7 +219,7 @@ void IMB_freeImBuf(ImBuf *ibuf) IMB_freezbufImBuf(ibuf); IMB_freezbuffloatImBuf(ibuf); freeencodedbufferImBuf(ibuf); - IMB_metadata_free(ibuf); + IMB_metadata_free(ibuf->metadata); colormanage_cache_free(ibuf); if (ibuf->dds_data.data != NULL) { diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index e28c8122006..b2197ecb3b5 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -49,6 +49,7 @@ #include "IMB_filetype.h" #include "IMB_filter.h" #include "IMB_moviecache.h" +#include "IMB_metadata.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 35c7b6363a1..ef9217fbc8c 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -382,7 +382,8 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla * the information when we write * it back to disk. */ - IMB_metadata_add_field(ibuf, "None", str); + IMB_metadata_ensure(&ibuf->metadata); + IMB_metadata_set_field(ibuf->metadata, "None", str); ibuf->flags |= IB_metadata; MEM_freeN(str); goto next_stamp_marker; @@ -408,7 +409,8 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla *value = '\0'; /* need finish the key string */ value++; - IMB_metadata_add_field(ibuf, key, value); + IMB_metadata_ensure(&ibuf->metadata); + IMB_metadata_set_field(ibuf->metadata, key, value); ibuf->flags |= IB_metadata; MEM_freeN(str); next_stamp_marker: diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index da39967a4fe..ef103f7afcf 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -45,97 +45,69 @@ #include "IMB_metadata.h" +#define METADATA_MAX_VALUE_LENGTH 1024 -void IMB_metadata_free(struct ImBuf *img) +void IMB_metadata_ensure(struct IDProperty **metadata) { - if (!img) + if (*metadata != NULL) { return; - if (!img->metadata) { + } + + IDPropertyTemplate val; + *metadata = IDP_New(IDP_GROUP, &val, "metadata"); +} + +void IMB_metadata_free(struct IDProperty *metadata) +{ + if (metadata == NULL) { return; } - IDP_FreeProperty(img->metadata); - MEM_freeN(img->metadata); + IDP_FreeProperty(metadata); + MEM_freeN(metadata); } -bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, const size_t len) +bool IMB_metadata_get_field(struct IDProperty *metadata, const char *key, char *field, const size_t len) { IDProperty *prop; - bool retval = false; - - if (!img) - return false; - if (!img->metadata) + if (metadata == NULL) { return false; + } - prop = IDP_GetPropertyFromGroup(img->metadata, key); + prop = IDP_GetPropertyFromGroup(metadata, key); if (prop && prop->type == IDP_STRING) { BLI_strncpy(field, IDP_String(prop), len); - retval = true; + return true; } - return retval; + return false; } void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb) { BLI_assert(dimb != simb); if (simb->metadata) { - IMB_metadata_free(dimb); + IMB_metadata_free(dimb->metadata); dimb->metadata = IDP_CopyProperty(simb->metadata); } } -bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value) +void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value) { - IDProperty *prop; - - if (!img) - return false; + BLI_assert(metadata); + IDProperty *prop = IDP_GetPropertyFromGroup(metadata, key); - if (!img->metadata) { - IDPropertyTemplate val; - img->metadata = IDP_New(IDP_GROUP, &val, "metadata"); + if (prop != NULL && prop->type != IDP_STRING) { + IDP_FreeFromGroup(metadata, prop); + prop = NULL; } - prop = IDP_NewString(value, key, 512); - return IDP_AddToGroup(img->metadata, prop); -} - -bool IMB_metadata_del_field(struct ImBuf *img, const char *key) -{ - IDProperty *prop; - - if ((!img) || (!img->metadata)) - return false; - - prop = IDP_GetPropertyFromGroup(img->metadata, key); - - if (prop) { - IDP_FreeFromGroup(img->metadata, prop); + if (prop == NULL) { + prop = IDP_NewString(value, key, METADATA_MAX_VALUE_LENGTH); + IDP_AddToGroup(metadata, prop); } - return false; -} - -bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field) -{ - IDProperty *prop; - if (!img) - return false; - - prop = (img->metadata) ? IDP_GetPropertyFromGroup(img->metadata, key) : NULL; - - if (!prop) { - return (IMB_metadata_add_field(img, key, field)); - } - else if (prop->type == IDP_STRING) { - IDP_AssignString(prop, field, 1024); - return true; - } - else { - return false; - } + IDP_AssignString(prop, value, METADATA_MAX_VALUE_LENGTH); } diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 4e85d70d382..ad04f1fb78d 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1790,12 +1790,13 @@ struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, const Header & header = file->header(0); Header::ConstIterator iter; + IMB_metadata_ensure(&ibuf->metadata); for (iter = header.begin(); iter != header.end(); iter++) { const StringAttribute *attrib = file->header(0).findTypedAttribute (iter.name()); /* not all attributes are string attributes so we might get some NULLs here */ if (attrib) { - IMB_metadata_add_field(ibuf, iter.name(), attrib->value().c_str()); + IMB_metadata_set_field(ibuf->metadata, iter.name(), attrib->value().c_str()); ibuf->flags |= IB_metadata; } } diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 857f72e10eb..29fbe79d8db 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -759,8 +759,9 @@ ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colors if (flags & IB_metadata) { png_text *text_chunks; int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL); + IMB_metadata_ensure(&ibuf->metadata); for (int i = 0; i < count; i++) { - IMB_metadata_add_field(ibuf, text_chunks[i].key, text_chunks[i].text); + IMB_metadata_set_field(ibuf->metadata, text_chunks[i].key, text_chunks[i].text); ibuf->flags |= IB_metadata; } } diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 3c587684641..2fa5b5a0170 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -430,16 +430,17 @@ static ImBuf *thumb_create_ex( IMB_scaleImBuf(img, ex, ey); } BLI_snprintf(desc, sizeof(desc), "Thumbnail for %s", uri); - IMB_metadata_change_field(img, "Description", desc); - IMB_metadata_change_field(img, "Software", "Blender"); - IMB_metadata_change_field(img, "Thumb::URI", uri); - IMB_metadata_change_field(img, "Thumb::MTime", mtime); + IMB_metadata_ensure(&img->metadata); + IMB_metadata_set_field(img->metadata, "Software", "Blender"); + IMB_metadata_set_field(img->metadata, "Thumb::URI", uri); + IMB_metadata_set_field(img->metadata, "Description", desc); + IMB_metadata_set_field(img->metadata, "Thumb::MTime", mtime); if (use_hash) { - IMB_metadata_change_field(img, "X-Blender::Hash", hash); + IMB_metadata_set_field(img->metadata, "X-Blender::Hash", hash); } if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) { - IMB_metadata_change_field(img, "Thumb::Image::Width", cwidth); - IMB_metadata_change_field(img, "Thumb::Image::Height", cheight); + IMB_metadata_set_field(img->metadata, "Thumb::Image::Width", cwidth); + IMB_metadata_set_field(img->metadata, "Thumb::Image::Height", cheight); } img->ftype = IMB_FTYPE_PNG; img->planes = 32; @@ -589,7 +590,7 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash); - if (IMB_metadata_get_field(img, "Thumb::MTime", mtime, sizeof(mtime))) { + if (IMB_metadata_get_field(img->metadata, "Thumb::MTime", mtime, sizeof(mtime))) { regenerate = (st.st_mtime != atol(mtime)); } else { @@ -598,7 +599,7 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source } if (use_hash && !regenerate) { - if (IMB_metadata_get_field(img, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr))) { + if (IMB_metadata_get_field(img->metadata, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr))) { regenerate = !STREQ(thumb_hash, thumb_hash_curr); } else { diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 201e11aca77..67c87d5d9b8 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -84,6 +84,7 @@ #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_metadata.h" #include "RE_engine.h" #include "RE_pipeline.h" -- cgit v1.2.3 From 6374d390d366e582465dc7cfb62e0443b060cc6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 5 Apr 2018 16:31:59 +0200 Subject: Write StampData metadata to video files This is currently only supported by FFmpeg (so not frameserver, AVI RAW, or AVI JPEG), and only seems to work when using Matroska or Ogg Theora containers. Only metadata that doesn't change from frame to frame is written to video files. This distinction is visible in the UI by looking at the stamp checkbox tooltips (they either mention "image" or "image/video"). Part of: https://developer.blender.org/D2273 Reviewed by: @campbellbarton --- source/blender/blenkernel/BKE_image.h | 5 +++ source/blender/blenkernel/intern/image.c | 43 +++++++++++++++++++------- source/blender/blenkernel/intern/writeffmpeg.c | 26 ++++++++++++++-- source/blender/makesrna/intern/rna_scene.c | 8 ++--- 4 files changed, 65 insertions(+), 17 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 57459412efc..1af123759e6 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -67,6 +67,11 @@ void BKE_image_init(struct Image *image); typedef void (StampCallback)(void *data, const char *propname, char *propvalue, int len); void BKE_render_result_stamp_info(struct Scene *scene, struct Object *camera, struct RenderResult *rr, bool allocate_only); +/** + * Fills in the static stamp data (i.e. everything except things that can change per frame). + * The caller is responsible for freeing the allocated memory. + */ +struct StampData *BKE_stamp_info_from_scene_static(struct Scene *scene); void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf); void BKE_stamp_info_from_imbuf(struct RenderResult *rr, struct ImBuf *ibuf); void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index e65692fb1b4..34891d95669 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1623,6 +1623,7 @@ typedef struct StampData { char marker[512]; char time[512]; char frame[512]; + char frame_range[512]; char camera[STAMP_NAME_SIZE]; char cameralens[STAMP_NAME_SIZE]; char scene[STAMP_NAME_SIZE]; @@ -1639,7 +1640,12 @@ typedef struct StampData { } StampData; #undef STAMP_NAME_SIZE -static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int do_prefix) +/** + * \param do_prefix: Include a label like "File ", "Date ", etc. in the stamp data strings. + * \param use_dynamic: Also include data that can change on a per-frame basis. + */ +static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int do_prefix, + bool use_dynamic) { char text[256]; struct tm *tl; @@ -1670,7 +1676,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d stamp_data->date[0] = '\0'; } - if (scene->r.stamp & R_STAMP_MARKER) { + if (use_dynamic && scene->r.stamp & R_STAMP_MARKER) { const char *name = BKE_scene_find_last_marker_name(scene, CFRA); if (name) BLI_strncpy(text, name, sizeof(text)); @@ -1682,7 +1688,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d stamp_data->marker[0] = '\0'; } - if (scene->r.stamp & R_STAMP_TIME) { + if (use_dynamic && scene->r.stamp & R_STAMP_TIME) { const short timecode_style = USER_TIMECODE_SMPTE_FULL; BLI_timecode_string_from_time(text, sizeof(text), 0, FRA2TIME(scene->r.cfra), FPS, timecode_style); BLI_snprintf(stamp_data->time, sizeof(stamp_data->time), do_prefix ? "Timecode %s" : "%s", text); @@ -1691,7 +1697,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d stamp_data->time[0] = '\0'; } - if (scene->r.stamp & R_STAMP_FRAME) { + if (use_dynamic && scene->r.stamp & R_STAMP_FRAME) { char fmtstr[32]; int digits = 1; @@ -1705,14 +1711,14 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d stamp_data->frame[0] = '\0'; } - if (scene->r.stamp & R_STAMP_CAMERA) { + if (use_dynamic && scene->r.stamp & R_STAMP_CAMERA) { BLI_snprintf(stamp_data->camera, sizeof(stamp_data->camera), do_prefix ? "Camera %s" : "%s", camera ? camera->id.name + 2 : ""); } else { stamp_data->camera[0] = '\0'; } - if (scene->r.stamp & R_STAMP_CAMERALENS) { + if (use_dynamic && scene->r.stamp & R_STAMP_CAMERALENS) { if (camera && camera->type == OB_CAMERA) { BLI_snprintf(text, sizeof(text), "%.2f", ((Camera *)camera->data)->lens); } @@ -1733,7 +1739,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d stamp_data->scene[0] = '\0'; } - if (scene->r.stamp & R_STAMP_SEQSTRIP) { + if (use_dynamic && scene->r.stamp & R_STAMP_SEQSTRIP) { Sequence *seq = BKE_sequencer_foreground_frame_get(scene, scene->r.cfra); if (seq) BLI_strncpy(text, seq->name + 2, sizeof(text)); @@ -1749,7 +1755,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d Render *re = RE_GetSceneRender(scene); RenderStats *stats = re ? RE_GetStats(re) : NULL; - if (stats && (scene->r.stamp & R_STAMP_RENDERTIME)) { + if (use_dynamic && stats && (scene->r.stamp & R_STAMP_RENDERTIME)) { BLI_timecode_string_from_time_simple(text, sizeof(text), stats->lastframetime); BLI_snprintf(stamp_data->rendertime, sizeof(stamp_data->rendertime), do_prefix ? "RenderTime %s" : "%s", text); @@ -1758,7 +1764,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d stamp_data->rendertime[0] = '\0'; } - if (stats && (scene->r.stamp & R_STAMP_MEMORY)) { + if (use_dynamic && stats && (scene->r.stamp & R_STAMP_MEMORY)) { BLI_snprintf(stamp_data->memory, sizeof(stamp_data->memory), do_prefix ? "Peak Memory %.2fM" : "%.2fM", stats->mem_peak); } else { @@ -1885,7 +1891,7 @@ void BKE_image_stamp_buf( display = IMB_colormanagement_display_get_named(display_device); if (stamp_data_template == NULL) { - stampdata(scene, camera, &stamp_data, (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0); + stampdata(scene, camera, &stamp_data, (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0, true); } else { stampdata_from_template(&stamp_data, scene, stamp_data_template); @@ -2106,13 +2112,28 @@ void BKE_render_result_stamp_info(Scene *scene, Object *camera, struct RenderRes } if (!allocate_only) - stampdata(scene, camera, stamp_data, 0); + stampdata(scene, camera, stamp_data, 0, true); if (!rr->stamp_data) { rr->stamp_data = stamp_data; } } +struct StampData *BKE_stamp_info_from_scene_static(Scene *scene) +{ + struct StampData *stamp_data; + + if (!(scene && (scene->r.stamp & R_STAMP_ALL))) + return NULL; + + /* Memory is allocated here (instead of by the caller) so that the caller + * doesn't have to know the size of the StampData struct. */ + stamp_data = MEM_callocN(sizeof(StampData), __func__); + stampdata(scene, NULL, stamp_data, 0, false); + + return stamp_data; +} + void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip) { if ((callback == NULL) || (stamp_data == NULL)) { diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 5415fbb8ae1..aa81b39d196 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -53,6 +53,7 @@ #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_image.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_sound.h" @@ -62,6 +63,8 @@ #include "ffmpeg_compat.h" +struct StampData; + typedef struct FFMpegContext { int ffmpeg_type; int ffmpeg_codec; @@ -94,6 +97,8 @@ typedef struct FFMpegContext { bool audio_deinterleave; int audio_sample_size; + struct StampData *stamp_data; + #ifdef WITH_AUDASPACE AUD_Device *audio_mixdown_device; #endif @@ -836,6 +841,12 @@ static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float va av_dict_set(dict, key, buffer, 0); } +static void ffmpeg_add_metadata_callback(void *data, const char *propname, char *propvalue, int len) +{ + AVDictionary **metadata = (AVDictionary **)data; + av_dict_set(metadata, propname, propvalue, 0); +} + static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports) { /* Handle to the output file */ @@ -994,6 +1005,11 @@ static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int goto fail; } } + + if (context->stamp_data != NULL) { + BKE_stamp_info_callback(&of->metadata, context->stamp_data, ffmpeg_add_metadata_callback, false); + } + if (avformat_write_header(of, NULL) < 0) { BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination"); goto fail; @@ -1168,6 +1184,7 @@ int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int r context->ffmpeg_autosplit_count = 0; context->ffmpeg_preview = preview; + context->stamp_data = BKE_stamp_info_from_scene_static(scene); success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports); #ifdef WITH_AUDASPACE @@ -1734,6 +1751,7 @@ void *BKE_ffmpeg_context_create(void) context->ffmpeg_autosplit = 0; context->ffmpeg_autosplit_count = 0; context->ffmpeg_preview = false; + context->stamp_data = NULL; return context; } @@ -1741,9 +1759,13 @@ void *BKE_ffmpeg_context_create(void) void BKE_ffmpeg_context_free(void *context_v) { FFMpegContext *context = context_v; - if (context) { - MEM_freeN(context); + if (context == NULL) { + return; + } + if (context->stamp_data) { + MEM_freeN(context->stamp_data); } + MEM_freeN(context); } #endif /* WITH_FFMPEG */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index e6ba459a406..94206710028 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -6355,7 +6355,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_stamp_date", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_DATE); - RNA_def_property_ui_text(prop, "Stamp Date", "Include the current date in image metadata"); + RNA_def_property_ui_text(prop, "Stamp Date", "Include the current date in image/video metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_stamp_frame", PROP_BOOLEAN, PROP_NONE); @@ -6375,12 +6375,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_stamp_scene", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_SCENE); - RNA_def_property_ui_text(prop, "Stamp Scene", "Include the name of the active scene in image metadata"); + RNA_def_property_ui_text(prop, "Stamp Scene", "Include the name of the active scene in image/video metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_stamp_note", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_NOTE); - RNA_def_property_ui_text(prop, "Stamp Note", "Include a custom note in image metadata"); + RNA_def_property_ui_text(prop, "Stamp Note", "Include a custom note in image/video metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_stamp_marker", PROP_BOOLEAN, PROP_NONE); @@ -6390,7 +6390,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_stamp_filename", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_FILENAME); - RNA_def_property_ui_text(prop, "Stamp Filename", "Include the .blend filename in image metadata"); + RNA_def_property_ui_text(prop, "Stamp Filename", "Include the .blend filename in image/video metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_stamp_sequencer_strip", PROP_BOOLEAN, PROP_NONE); -- cgit v1.2.3 From 6c3110a66122f33a3c4df3066c42374660dad067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 5 Apr 2018 16:33:32 +0200 Subject: Write the scene render frame range to image/video files This is useful to create a mapping from the frame range in the video to frame index in the blend file. Part of: https://developer.blender.org/D2273 Reviewed by: @campbellbarton --- source/blender/blenkernel/intern/image.c | 17 +++++++++++++++++ source/blender/makesdna/DNA_scene_types.h | 3 ++- source/blender/makesrna/intern/rna_scene.c | 5 +++++ 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 34891d95669..6abffd83a4d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1711,6 +1711,15 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d stamp_data->frame[0] = '\0'; } + if (scene->r.stamp & R_STAMP_FRAME_RANGE) { + BLI_snprintf(stamp_data->frame_range, sizeof(stamp_data->frame), + do_prefix ? "Frame Range %d:%d" : "%d:%d", + scene->r.sfra, scene->r.efra); + } + else { + stamp_data->frame_range[0] = '\0'; + } + if (use_dynamic && scene->r.stamp & R_STAMP_CAMERA) { BLI_snprintf(stamp_data->camera, sizeof(stamp_data->camera), do_prefix ? "Camera %s" : "%s", camera ? camera->id.name + 2 : ""); } @@ -1771,6 +1780,13 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d stamp_data->memory[0] = '\0'; } } + if (scene->r.stamp & R_STAMP_FRAME_RANGE) { + BLI_snprintf(stamp_data->frame_range, sizeof(stamp_data->frame_range), + do_prefix ? "Frame Range %d:%d" : "%d:%d", scene->r.sfra, scene->r.efra); + } + else { + stamp_data->frame_range[0] = '\0'; + } } /* Will always add prefix. */ @@ -2151,6 +2167,7 @@ void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCall CALL(marker, "Marker"); CALL(time, "Time"); CALL(frame, "Frame"); + CALL(frame_range, "FrameRange"); CALL(camera, "Camera"); CALL(cameralens, "Lens"); CALL(scene, "Scene"); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b41e649b628..9a14f2eacbb 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1832,10 +1832,11 @@ enum { #define R_STAMP_STRIPMETA 0x1000 #define R_STAMP_MEMORY 0x2000 #define R_STAMP_HIDE_LABELS 0x4000 +#define R_STAMP_FRAME_RANGE 0x8000 #define R_STAMP_ALL (R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_CAMERA|R_STAMP_SCENE| \ R_STAMP_NOTE|R_STAMP_MARKER|R_STAMP_FILENAME|R_STAMP_SEQSTRIP| \ R_STAMP_RENDERTIME|R_STAMP_CAMERALENS|R_STAMP_MEMORY| \ - R_STAMP_HIDE_LABELS) + R_STAMP_HIDE_LABELS|R_STAMP_FRAME_RANGE) /* RenderData.alphamode */ #define R_ADDSKY 0 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 94206710028..2cfe0666fbf 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -6363,6 +6363,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Stamp Frame", "Include the frame number in image metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "use_stamp_frame_range", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_FRAME_RANGE); + RNA_def_property_ui_text(prop, "Stamp Frame", "Include the rendered frame range in image/video metadata"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "use_stamp_camera", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_CAMERA); RNA_def_property_ui_text(prop, "Stamp Camera", "Include the name of the active camera in image metadata"); -- cgit v1.2.3 From ea0e2f9bd3849b73a29ef1805988fdb0484bc9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 5 Apr 2018 16:34:36 +0200 Subject: Load metadata from video files and expose via RNA The MovieSequence and MovieClip classes now have a metadata() function that exposes the `IDProperty *` holding the video metadata. Part of: https://developer.blender.org/D2273 Reviewed by: @campbellbarton --- source/blender/blenkernel/intern/sequencer.c | 4 +++ source/blender/imbuf/IMB_metadata.h | 1 + source/blender/imbuf/intern/IMB_anim.h | 3 +++ source/blender/imbuf/intern/anim_movie.c | 22 ++++++++++++++++ source/blender/makesrna/intern/rna_ID.c | 23 +++++++++++++++++ source/blender/makesrna/intern/rna_movieclip.c | 28 +++++++++++++++++++++ source/blender/makesrna/intern/rna_sequencer.c | 35 +++++++++++++++++++++++++- 7 files changed, 115 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 1e61ff526ef..0cc151c3645 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -943,6 +943,8 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r return; } + IMB_anim_load_metadata(sanim->anim); + seq->len = IMB_anim_get_duration(sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN); seq->anim_preseek = IMB_anim_get_preseek(sanim->anim); @@ -5382,6 +5384,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad } } + IMB_anim_load_metadata(anim_arr[0]); + seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]); BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2); BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); diff --git a/source/blender/imbuf/IMB_metadata.h b/source/blender/imbuf/IMB_metadata.h index 258d6bb1c5a..0a0d2c1faf6 100644 --- a/source/blender/imbuf/IMB_metadata.h +++ b/source/blender/imbuf/IMB_metadata.h @@ -73,5 +73,6 @@ bool IMB_metadata_get_field(struct IDProperty *metadata, const char *key, char * void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value); void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb); +struct IDProperty *IMB_anim_load_metadata(struct anim *anim); #endif /* __IMB_METADATA_H__ */ diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index c4c4f4405a5..6fa31e122cc 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -93,6 +93,7 @@ struct _AviMovie; struct anim_index; +struct IDProperty; struct anim { int ib_flags; @@ -158,6 +159,8 @@ struct anim { char colorspace[64]; char suffix[64]; /* MAX_NAME - multiview */ + + struct IDProperty *metadata; }; #endif diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index cc8a38d5bf4..f842b69418e 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -80,6 +80,7 @@ #include "IMB_anim.h" #include "IMB_indexer.h" +#include "IMB_metadata.h" #ifdef WITH_FFMPEG # include "BKE_global.h" /* ENDIAN_ORDER */ @@ -220,6 +221,7 @@ void IMB_free_anim(struct anim *anim) free_anim_ffmpeg(anim); #endif IMB_free_indices(anim); + IMB_metadata_free(anim->metadata); MEM_freeN(anim); } @@ -239,6 +241,26 @@ void IMB_close_anim_proxies(struct anim *anim) IMB_free_indices(anim); } +struct IDProperty *IMB_anim_load_metadata(struct anim *anim) +{ +#ifdef WITH_FFMPEG + AVDictionaryEntry *entry = NULL; + + BLI_assert(anim->pFormatCtx != NULL); + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "METADATA FETCH\n"); + + while (true) { + entry = av_dict_get(anim->pFormatCtx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX); + if (entry == NULL) break; + + /* Delay creation of the property group until there is actual metadata to put in there. */ + IMB_metadata_ensure(&anim->metadata); + IMB_metadata_set_field(anim->metadata, entry->key, entry->value); + } +#endif + return anim->metadata; +} + struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE]) { struct anim *anim; diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index a9e34247cbd..bc2c26c2b2b 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -754,6 +754,14 @@ static PointerRNA rna_IDPreview_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_ImagePreview, prv_img); } +static IDProperty *rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr, bool UNUSED(create)) +{ + if (ptr == NULL) { + return NULL; + } + return ptr->data; +} + #else static void rna_def_ID_properties(BlenderRNA *brna) @@ -1105,6 +1113,20 @@ static void rna_def_library(BlenderRNA *brna) RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Reload this library and all its linked data-blocks"); } + +/** + * \attention This is separate from the above. It allows for RNA functions to + * return an IDProperty *. See MovieClip.metadata for a usage example. + **/ +static void rna_def_idproperty_wrap_ptr(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "IDPropertyWrapPtr", NULL); + RNA_def_struct_idprops_func(srna, "rna_IDPropertyWrapPtr_idprops"); + RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); +} + void RNA_def_ID(BlenderRNA *brna) { StructRNA *srna; @@ -1122,6 +1144,7 @@ void RNA_def_ID(BlenderRNA *brna) rna_def_ID_properties(brna); rna_def_ID_materials(brna); rna_def_library(brna); + rna_def_idproperty_wrap_ptr(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index fb743f5236d..d63f3fe76f8 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -33,6 +33,7 @@ #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" +#include "RNA_access.h" #include "RNA_define.h" #include "rna_internal.h" @@ -44,6 +45,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_metadata.h" #ifdef RNA_RUNTIME @@ -103,6 +105,22 @@ static void rna_MovieClipUser_proxy_render_settings_update(Main *UNUSED(bmain), } } +static PointerRNA rna_MovieClip_metadata_get(MovieClip *clip) +{ + if (clip == NULL || clip->anim == NULL) { + return PointerRNA_NULL; + } + + IDProperty *metadata = IMB_anim_load_metadata(clip->anim); + if (metadata == NULL) { + return PointerRNA_NULL; + } + + PointerRNA ptr; + RNA_pointer_create(NULL, &RNA_IDPropertyWrapPtr, metadata, &ptr); + return ptr; +} + #else static void rna_def_movieclip_proxy(BlenderRNA *brna) @@ -257,6 +275,8 @@ static void rna_def_movieclip(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; + PropertyRNA *parm; static const EnumPropertyItem clip_source_items[] = { {MCLIP_SRC_SEQUENCE, "SEQUENCE", 0, "Image Sequence", "Multiple image files, as a sequence"}, @@ -348,6 +368,14 @@ static void rna_def_movieclip(BlenderRNA *brna) RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings"); RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings"); + /* metadata */ + func = RNA_def_function(srna, "metadata", "rna_MovieClip_metadata_get"); + RNA_def_function_ui_description(func, "Retrieve metadata of the movie file"); + /* return type */ + parm = RNA_def_pointer(func, "metadata", "IDPropertyWrapPtr", "", "Dict-like object containing the metadata"); + RNA_def_parameter_flags(parm, 0, PARM_RNAPTR); + RNA_def_function_return(func, parm); + rna_def_animdata_common(srna); } diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 81c05433e66..33621af69af 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -41,6 +41,8 @@ #include "BKE_sequencer.h" #include "BKE_sound.h" +#include "IMB_metadata.h" + #include "MEM_guardedalloc.h" #include "RNA_access.h" @@ -587,6 +589,27 @@ static IDProperty *rna_Sequence_idprops(PointerRNA *ptr, bool create) return seq->prop; } +static PointerRNA rna_MovieSequence_metadata_get(Sequence *seq) +{ + if (seq == NULL || seq->anims.first == NULL) { + return PointerRNA_NULL; + } + + StripAnim *sanim = seq->anims.first; + if (sanim->anim == NULL) { + return PointerRNA_NULL; + } + + IDProperty *metadata = IMB_anim_load_metadata(sanim->anim); + if (metadata == NULL) { + return PointerRNA_NULL; + } + + PointerRNA ptr; + RNA_pointer_create(NULL, &RNA_IDPropertyWrapPtr, metadata, &ptr); + return ptr; +} + static PointerRNA rna_SequenceEditor_meta_stack_get(CollectionPropertyIterator *iter) { ListBaseIterator *internal = &iter->internal.listbase; @@ -1963,7 +1986,9 @@ static void rna_def_movie(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + FunctionRNA *func; + PropertyRNA *parm; + srna = RNA_def_struct(brna, "MovieSequence", "Sequence"); RNA_def_struct_ui_text(srna, "Movie Sequence", "Sequence strip to load a video"); RNA_def_struct_sdna(srna, "Sequence"); @@ -1995,6 +2020,14 @@ static void rna_def_movie(BlenderRNA *brna) "rna_Sequence_filepath_set"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_filepath_update"); + /* metadata */ + func = RNA_def_function(srna, "metadata", "rna_MovieSequence_metadata_get"); + RNA_def_function_ui_description(func, "Retrieve metadata of the movie file"); + /* return type */ + parm = RNA_def_pointer(func, "metadata", "IDPropertyWrapPtr", "", "Dict-like object containing the metadata"); + RNA_def_parameter_flags(parm, 0, PARM_RNAPTR); + RNA_def_function_return(func, parm); + /* multiview */ prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_VIEWS); -- cgit v1.2.3