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') 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