Merge branch 'master' into blender2.8
authorSybren A. Stüvel <sybren@stuvel.eu>
Thu, 5 Apr 2018 14:58:41 +0000 (16:58 +0200)
committerSybren A. Stüvel <sybren@stuvel.eu>
Thu, 5 Apr 2018 14:58:41 +0000 (16:58 +0200)
26 files changed:
release/scripts/startup/bl_ui/properties_render.py
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenlib/BLI_string.h
source/blender/editors/screen/area.c
source/blender/imbuf/CMakeLists.txt
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/IMB_metadata.h [moved from source/blender/imbuf/intern/IMB_metadata.h with 53% similarity]
source/blender/imbuf/intern/IMB_anim.h
source/blender/imbuf/intern/allocimbuf.c
source/blender/imbuf/intern/anim_movie.c
source/blender/imbuf/intern/colormanagement.c
source/blender/imbuf/intern/jpeg.c
source/blender/imbuf/intern/metadata.c
source/blender/imbuf/intern/openexr/openexr_api.cpp
source/blender/imbuf/intern/png.c
source/blender/imbuf/intern/thumbs.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_ID.c
source/blender/makesrna/intern/rna_movieclip.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/render/intern/source/pipeline.c

index ed926b51a9c147c6cd09da3da5ad6ba03e67a24a..b644b6f0a86290dcd435ef5c9c28aaa31812624f 100644 (file)
@@ -395,6 +395,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
         col.prop(rd, "use_stamp_camera", text="Camera")
         col.prop(rd, "use_stamp_lens", text="Lens")
         col.prop(rd, "use_stamp_filename", text="Filename")
+        col.prop(rd, "use_stamp_frame_range", text="Frame range")
         col.prop(rd, "use_stamp_marker", text="Marker")
         col.prop(rd, "use_stamp_sequencer_strip", text="Seq. Strip")
 
index 57459412efc089ec099c83a4b448256073867902..1af123759e6ef1ce752710069a482fe16fa7b49e 100644 (file)
@@ -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);
index d421d780343d2ac979293407942fd04a4ed4113f..ef48b3c1a456e2fb5048259ad1fc50d98da7dd7e 100644 (file)
@@ -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"
@@ -1623,6 +1624,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 +1641,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 +1677,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 +1689,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 +1698,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 +1712,23 @@ 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 (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 : "<none>");
        }
        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 +1749,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 +1765,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,13 +1774,20 @@ 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 {
                        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. */
@@ -1885,7 +1908,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 +2129,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)) {
@@ -2130,6 +2168,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");
@@ -2173,27 +2212,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);
 }
 
index ee80438db6442fe002efe712e9550cc1baef07a5..49f120de2502ff996a643472b8e0afe08240d27c 100644 (file)
@@ -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"
 
index 184016100c4cba2d732dc7ed0f3b716fba87cb8c..263c30cabca8c00d54139c7379290a85335dc99f 100644 (file)
@@ -86,6 +86,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"
@@ -946,6 +947,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);
@@ -5392,6 +5395,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);
index f745a840ceaab33b3255eb31a0cb5882ae64fbc4..85582ceea4c2d4420b3542b4a89776ee9f3bc659 100644 (file)
@@ -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 */
index d137806c57549367a7f82d42031e90986f7bd334..48be9d1842f1d2037d36e0502486c52492b88214 100644 (file)
@@ -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
index 3b899a3d302672b4901fb4421f6f2447d7f80f63..390098b3ea38017bb1f0395d89b4953253ae424b 100644 (file)
@@ -66,6 +66,7 @@
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
+#include "IMB_metadata.h"
 
 #include "UI_interface.h"
 #include "UI_interface_icons.h"
@@ -2249,7 +2250,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)
index c3950d8eb83445a125ade059d90861d198a1adc9..e73f227dec8a2eb49f637d518666dc7f846155e2 100644 (file)
@@ -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
index a0fc273a74686ea43e4a52e05e5bf0897f9714b6..e5cd21a3248f224db1672d86f531039f48d3ec87 100644 (file)
@@ -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,
similarity index 53%
rename from source/blender/imbuf/intern/IMB_metadata.h
rename to source/blender/imbuf/IMB_metadata.h
index bc0b2c70ecbf5aa6a5e25b0dab7f9df8f6de7a21..0a0d2c1faf6bc41ad15d6a6b235ced46d196606e 100644 (file)
@@ -4,7 +4,7 @@
  * 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. 
+ * 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
@@ -33,7 +33,9 @@
 #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.
@@ -41,26 +43,36 @@ struct ImBuf;
  * '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);
 
-/* free blender ImMetaData struct */
-void IMB_metadata_free(struct ImBuf *img);
+/** 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 ImMetaData struct, which has to be allocated with IMB_metadata_create
- *  before calling this function.
- *  \param img - the ImBuf that contains the image data
+/** 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
- *  \return    - 1 (true) if ImageInfo present, 0 (false) otherwise
  */
-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);
 
-/** 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);
+void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb);
+struct IDProperty *IMB_anim_load_metadata(struct anim *anim);
 
 #endif /* __IMB_METADATA_H__ */
index c4c4f4405a50e43ffd210461af8f9530b6415472..6fa31e122cc03d75ce1a0caf90f3ffa72644aee3 100644 (file)
@@ -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
index 7fc4a65d8d79315e7eb3c6e30eb2f647a20436dc..faa0b5f7b6e6421dac4fa9fffbc86892ad84ffd8 100644 (file)
@@ -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) {
index cc8a38d5bf4671c536a3be5109553079f25e4e9d..f842b69418e2e52922a6fc056a31008206a8ed1e 100644 (file)
@@ -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;
index e28c812200603afc0290346d652c995375f56f37..b2197ecb3b5a8dea7fa7fa0081034aed950d2b35 100644 (file)
@@ -49,6 +49,7 @@
 #include "IMB_filetype.h"
 #include "IMB_filter.h"
 #include "IMB_moviecache.h"
+#include "IMB_metadata.h"
 
 #include "MEM_guardedalloc.h"
 
index 35c7b6363a1e8512630c942cd1d3509b4b1c2b75..ef9217fbc8ca0988ec186446e9f5b70df1973b01 100644 (file)
@@ -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:
index da39967a4fe218ebf13c571a2d4d96edaec486e5..ef103f7afcff2f3cd7a96afc82f404ce3a17ea22 100644 (file)
 
 #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);
 }
index 4e85d70d3829a56dac489ccd6d3a73725c4bd49d..ad04f1fb78d68c6d17d1cd9822eeeccae63f2050 100644 (file)
@@ -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 <StringAttribute> (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;
                                                }
                                        }
index 857f72e10eb4a66f2bc5818adca28ff87dd7633a..29fbe79d8dbe708463d089a5f80ae46f63113f99 100644 (file)
@@ -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;
                        }
                }
index ba72decf44d3326403a7c2b9a799ee3d72b39549..86e1fba9af79c44bb69d77753cff5c943a20a2da 100644 (file)
@@ -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 {
index d2810efca08c19f34acbb36b291ed0f5f0ceab5f..a18c9cf3712257a05bf90ef0fef05131022bd6b1 100644 (file)
@@ -1834,10 +1834,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
index c35ca5c42e41db852ba34aa3575d3d4a90522f10..088b2b67af5bacede78ea2d9e8c6439b810d0b07 100644 (file)
@@ -793,6 +793,14 @@ static int rna_ID_is_updated_data_get(PointerRNA *ptr)
        return ((data->recalc & ID_RECALC_ALL) != 0);
 }
 
+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)
@@ -1180,6 +1188,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;
@@ -1198,6 +1220,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
index 850b1cd706b9a2ff6a9bdfd6e1a67a95e2ac8f0e..c663119eb42a66fce9b59a5aafa7e7416501dea3 100644 (file)
@@ -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);
 }
 
index 5d91cd50935ed447267e5b0e8067cb2b89daa302..ac9fce46384b9f42d981d5c6cc04160a2c0c021d 100644 (file)
@@ -6137,7 +6137,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);
@@ -6145,6 +6145,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");
@@ -6157,12 +6162,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);
@@ -6172,7 +6177,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);
index 81c05433e668ab72e7e707dd52e550524e1c9ad7..33621af69afa60b4ee207ae115f7400043518c7a 100644 (file)
@@ -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);
index 84b64b8429869f7a8298758eabdfc22c7935c640..d6e45788942c49811d55f9f8a36a0ef77ac8a6a5 100644 (file)
@@ -88,6 +88,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"