diff options
Diffstat (limited to 'source/blender/blenkernel/intern/sequencer.c')
-rw-r--r-- | source/blender/blenkernel/intern/sequencer.c | 1425 |
1 files changed, 1103 insertions, 322 deletions
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index c9647b05ce7..f0e59eda321 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -53,7 +53,13 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" -#include "BLF_translation.h" +#ifdef WIN32 +# include "BLI_winstuff.h" +#else +# include <unistd.h> +#endif + +#include "BLT_translation.h" #include "BKE_animsys.h" #include "BKE_depsgraph.h" @@ -66,6 +72,7 @@ #include "BKE_scene.h" #include "BKE_mask.h" #include "BKE_library.h" +#include "BKE_idprop.h" #include "RNA_access.h" @@ -81,13 +88,15 @@ #include "BKE_sound.h" #ifdef WITH_AUDASPACE -# include "AUD_C-API.h" +# include AUD_SPECIAL_H #endif static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seqbasep, float cfra, int chanshown); static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, float cfra); static void seq_free_animdata(Scene *scene, Sequence *seq); static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr, bool make_float); +static size_t seq_num_files(Scene *scene, char views_format, const bool is_multiview); +static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const size_t view_id); /* **** XXX ******** */ #define SELECT 1 @@ -180,10 +189,7 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach if (seq->strip) seq_free_strip(seq->strip); - if (seq->anim) { - IMB_free_anim(seq->anim); - seq->anim = NULL; - } + BKE_sequence_free_anim(seq); if (seq->type & SEQ_TYPE_EFFECT) { struct SeqEffectHandle sh = BKE_sequence_get_effect(seq); @@ -195,6 +201,10 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach ((ID *)seq->sound)->us--; } + if (seq->stereo3d_format) { + MEM_freeN(seq->stereo3d_format); + } + /* clipboard has no scene and will never have a sound handle or be active * same goes to sequences copy for proxy rebuild job */ @@ -205,11 +215,16 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach ed->act_seq = NULL; if (seq->scene_sound && ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) - sound_remove_scene_sound(scene, seq->scene_sound); + BKE_sound_remove_scene_sound(scene, seq->scene_sound); seq_free_animdata(scene, seq); } + if (seq->prop) { + IDP_FreeProperty(seq->prop); + MEM_freeN(seq->prop); + } + /* free modifiers */ BKE_sequence_modifier_clear(seq); @@ -234,6 +249,22 @@ void BKE_sequence_free(Scene *scene, Sequence *seq) BKE_sequence_free_ex(scene, seq, true); } +/* Function to free imbuf and anim data on changes */ +void BKE_sequence_free_anim(Sequence *seq) +{ + while (seq->anims.last) { + StripAnim *sanim = seq->anims.last; + + if (sanim->anim) { + IMB_free_anim(sanim->anim); + sanim->anim = NULL; + } + + BLI_freelinkN(&seq->anims, sanim); + } + BLI_listbase_clear(&seq->anims); +} + /* cache must be freed before calling this function * since it leaves the seqbase in an invalid state */ static void seq_free_sequence_recurse(Scene *scene, Sequence *seq) @@ -257,26 +288,15 @@ Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc) return scene->ed; } -static void seq_free_clipboard_recursive(Sequence *seq_parent) -{ - Sequence *seq, *nseq; - - for (seq = seq_parent->seqbase.first; seq; seq = nseq) { - nseq = seq->next; - seq_free_clipboard_recursive(seq); - } - - BKE_sequence_clipboard_pointers_free(seq_parent); - BKE_sequence_free_ex(NULL, seq_parent, false); -} - void BKE_sequencer_free_clipboard(void) { Sequence *seq, *nseq; + BKE_sequencer_base_clipboard_pointers_free(&seqbase_clipboard); + for (seq = seqbase_clipboard.first; seq; seq = nseq) { nseq = seq->next; - seq_free_clipboard_recursive(seq); + seq_free_sequence_recurse(NULL, seq); } BLI_listbase_clear(&seqbase_clipboard); } @@ -327,7 +347,7 @@ static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt) { id_restore = BLI_findstring(lb, ((bSound *)ID_PT)->name, offsetof(bSound, name)); if (id_restore == NULL) { - id_restore = sound_new_file(bmain, ((bSound *)ID_PT)->name); + id_restore = BKE_sound_new_file(bmain, ((bSound *)ID_PT)->name); (ID_PT)->newid = id_restore; /* reuse next time */ } break; @@ -373,6 +393,33 @@ void BKE_sequence_clipboard_pointers_restore(Sequence *seq, Main *bmain) seqclipboard_ptr_restore(bmain, (ID **)&seq->mask); seqclipboard_ptr_restore(bmain, (ID **)&seq->sound); } + +/* recursive versions of funcions above */ +void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_free(seq); + BKE_sequencer_base_clipboard_pointers_free(&seq->seqbase); + } +} +void BKE_sequencer_base_clipboard_pointers_store(ListBase *seqbase) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_store(seq); + BKE_sequencer_base_clipboard_pointers_store(&seq->seqbase); + } +} +void BKE_sequencer_base_clipboard_pointers_restore(ListBase *seqbase, Main *bmain) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_restore(seq, bmain); + BKE_sequencer_base_clipboard_pointers_restore(&seq->seqbase, bmain); + } +} + /* end clipboard pointer mess */ @@ -499,24 +546,23 @@ void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixe /*********************** sequencer pipeline functions *************************/ -SeqRenderData BKE_sequencer_new_render_data(EvaluationContext *eval_ctx, - Main *bmain, Scene *scene, int rectx, int recty, - int preview_render_size) -{ - SeqRenderData rval; - - rval.bmain = bmain; - rval.scene = scene; - rval.rectx = rectx; - rval.recty = recty; - rval.preview_render_size = preview_render_size; - rval.motion_blur_samples = 0; - rval.motion_blur_shutter = 0; - rval.eval_ctx = eval_ctx; - rval.skip_cache = false; - rval.is_proxy_render = false; - - return rval; +void BKE_sequencer_new_render_data( + EvaluationContext *eval_ctx, + Main *bmain, Scene *scene, int rectx, int recty, + int preview_render_size, + SeqRenderData *r_context) +{ + r_context->eval_ctx = eval_ctx; + r_context->bmain = bmain; + r_context->scene = scene; + r_context->rectx = rectx; + r_context->recty = recty; + r_context->preview_render_size = preview_render_size; + r_context->motion_blur_samples = 0; + r_context->motion_blur_shutter = 0; + r_context->skip_cache = false; + r_context->is_proxy_render = false; + r_context->view_id = 0; } /* ************************* iterator ************************** */ @@ -638,7 +684,7 @@ static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metase if (seq->start + seq->len - seq->endofs > end) endofs = seq->start + seq->len - end; - sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs, + BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs, seq->start + seq->len - endofs, startofs + seq->anim_startofs); } } @@ -751,10 +797,17 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq) } } +static void seq_multiview_name(Scene *scene, const size_t view_id, const char *prefix, + const char *ext, char *r_path, size_t r_size) +{ + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id); + BLI_snprintf(r_path, r_size, "%s%s%s", prefix, suffix, ext); +} + /* note: caller should run BKE_sequence_calc(scene, seq) after */ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_range) { - char str[FILE_MAX]; + char path[FILE_MAX]; int prev_startdisp = 0, prev_enddisp = 0; /* note: don't rename the strip, will break animation curves */ @@ -787,22 +840,67 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r break; } case SEQ_TYPE_MOVIE: - BLI_join_dirfile(str, sizeof(str), seq->strip->dir, + { + StripAnim *sanim; + bool is_multiview_loaded = false; + const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && + (scene->r.scemode & R_MULTIVIEW) != 0; + + BLI_join_dirfile(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); - BLI_path_abs(str, G.main->name); + BLI_path_abs(path, G.main->name); + + BKE_sequence_free_anim(seq); + + if (is_multiview && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) { + char prefix[FILE_MAX]; + const char *ext = NULL; + size_t totfiles = seq_num_files(scene, seq->views_format, true); + int i = 0; + + BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); + + if (prefix[0] != '\0') { + for (i = 0; i < totfiles; i++) { + struct anim *anim; + char str[FILE_MAX]; - if (seq->anim) IMB_free_anim(seq->anim); + seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); + anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + + if (anim) { + seq_anim_add_suffix(scene, anim, i); + sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); + sanim->anim = anim; + } + } + is_multiview_loaded = true; + } + } + + if (is_multiview_loaded == false) { + struct anim *anim; + anim = openanim(path, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + if (anim) { + sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); + sanim->anim = anim; + } + } - seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, seq->strip->colorspace_settings.name); + /* use the first video as reference for everything */ + sanim = seq->anims.first; - if (!seq->anim) { + if ((!sanim) || (!sanim->anim)) { return; } - seq->len = IMB_anim_get_duration(seq->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN); - - seq->anim_preseek = IMB_anim_get_preseek(seq->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); seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; @@ -810,6 +908,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r seq->len = 0; } break; + } case SEQ_TYPE_MOVIECLIP: if (seq->clip == NULL) return; @@ -876,7 +975,6 @@ void BKE_sequencer_sort(Scene *scene) Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq, *seqt; - if (ed == NULL) return; @@ -1017,6 +1115,7 @@ static const char *give_seqname_by_type(int type) case SEQ_TYPE_ADJUSTMENT: return "Adjustment"; case SEQ_TYPE_SPEED: return "Speed"; case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur"; + case SEQ_TYPE_TEXT: return "Text"; default: return NULL; } @@ -1027,7 +1126,7 @@ const char *BKE_sequence_give_name(Sequence *seq) const char *name = give_seqname_by_type(seq->type); if (!name) { - if (seq->type < SEQ_TYPE_EFFECT) { + if (!(seq->type & SEQ_TYPE_EFFECT)) { return seq->strip->dir; } else { @@ -1063,30 +1162,25 @@ static void make_black_ibuf(ImBuf *ibuf) } } -static void multibuf(ImBuf *ibuf, float fmul) +static void multibuf(ImBuf *ibuf, const float fmul) { char *rt; float *rt_float; - int a, mul, icol; + int a; - mul = (int)(256.0f * fmul); rt = (char *)ibuf->rect; rt_float = ibuf->rect_float; if (rt) { + const int imul = (int)(256.0f * fmul); a = ibuf->x * ibuf->y; while (a--) { + rt[0] = min_ii((imul * rt[0]) >> 8, 255); + rt[1] = min_ii((imul * rt[1]) >> 8, 255); + rt[2] = min_ii((imul * rt[2]) >> 8, 255); + rt[3] = min_ii((imul * rt[3]) >> 8, 255); - icol = (mul * rt[0]) >> 8; - if (icol > 254) rt[0] = 255; else rt[0] = icol; - icol = (mul * rt[1]) >> 8; - if (icol > 254) rt[1] = 255; else rt[1] = icol; - icol = (mul * rt[2]) >> 8; - if (icol > 254) rt[2] = 255; else rt[2] = icol; - icol = (mul * rt[3]) >> 8; - if (icol > 254) rt[3] = 255; else rt[3] = icol; - rt += 4; } } @@ -1168,7 +1262,7 @@ static int evaluate_seq_frame_gen(Sequence **seq_arr, ListBase *seqbase, int cfr seq = seqbase->first; while (seq) { if (seq->startdisp <= cfra && seq->enddisp > cfra) { - if ((seq->type & SEQ_TYPE_EFFECT)) { + if ((seq->type & SEQ_TYPE_EFFECT) && !(seq->flag & SEQ_MUTE)) { if (seq->seq1) { effect_inputs[num_effect_inputs++] = seq->seq1; } @@ -1277,6 +1371,8 @@ typedef struct SeqIndexBuildContext { int tc_flags; int size_flags; int quality; + bool overwrite; + size_t view_id; Main *bmain; Scene *scene; @@ -1316,48 +1412,164 @@ static double seq_rendersize_to_scale_factor(int size) return 0.25; } -static void seq_open_anim_file(Sequence *seq) +/* the number of files will vary according to the stereo format */ +static size_t seq_num_files(Scene *scene, char views_format, const bool is_multiview) +{ + if (!is_multiview) { + return 1; + } + else if (views_format == R_IMF_VIEWS_STEREO_3D) { + return 1; + } + /* R_IMF_VIEWS_INDIVIDUAL */ + else { + return BKE_scene_multiview_num_views_get(&scene->r); + } +} + +static void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir) +{ + char dir[FILE_MAX]; + char fname[FILE_MAXFILE]; + + IMB_anim_get_fname(anim, fname, FILE_MAXFILE); + BLI_strncpy(dir, base_dir, sizeof(dir)); + BLI_path_append(dir, sizeof(dir), fname); + IMB_anim_set_index_dir(anim, dir); +} + +static void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile) { + char dir[FILE_MAX]; char name[FILE_MAX]; StripProxy *proxy; + bool use_proxy; + bool is_multiview_loaded = false; + Editing *ed = scene->ed; + const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && (scene->r.scemode & R_MULTIVIEW) != 0; - if (seq->anim != NULL) { + if ((seq->anims.first != NULL) && (((StripAnim *)seq->anims.first)->anim != NULL)) { return; } + /* reset all the previously created anims */ + BKE_sequence_free_anim(seq); + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(name, G.main->name); - - seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, seq->strip->colorspace_settings.name); - if (seq->anim == NULL) { - return; + proxy = seq->strip->proxy; + + use_proxy = proxy && ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) != 0 || + (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE)); + + if (use_proxy) { + if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { + if (ed->proxy_dir[0] == 0) + BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); + else + BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); + } + else { + BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + } + BLI_path_abs(dir, G.main->name); } - proxy = seq->strip->proxy; + if (is_multiview && seq->views_format == R_IMF_VIEWS_INDIVIDUAL) { + size_t totfiles = seq_num_files(scene, seq->views_format, true); + char prefix[FILE_MAX]; + const char *ext = NULL; + int i; - if (proxy == NULL) { - return; + BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext); + + if (prefix[0] != '\0') { + for (i = 0; i < totfiles; i++) { + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i); + char str[FILE_MAX]; + StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + + BLI_addtail(&seq->anims, sanim); + + BLI_snprintf(str, sizeof(str), "%s%s%s", prefix, suffix, ext); + + if (openfile) { + sanim->anim = openanim( + str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + else { + sanim->anim = openanim_noload( + str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + + if (sanim->anim) { +#if 0 + seq_anim_add_suffix(scene, sanim->anim, i); +#else + /* we already have the suffix */ + IMB_suffix_anim(sanim->anim, suffix); +#endif + } + else { + if (openfile) { + sanim->anim = openanim( + name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + else { + sanim->anim = openanim_noload( + name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + + /* no individual view files - monoscopic, stereo 3d or exr multiview */ + totfiles = 1; + } + + if (sanim->anim && use_proxy) { + seq_proxy_index_dir_set(sanim->anim, dir); + } + } + is_multiview_loaded = true; + } } - if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { - char dir[FILE_MAX]; - BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); - BLI_path_abs(dir, G.main->name); + if (is_multiview_loaded == false) { + StripAnim *sanim; + + sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); - IMB_anim_set_index_dir(seq->anim, dir); + if (openfile) { + sanim->anim = openanim( + name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + else { + sanim->anim = openanim_noload( + name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + + if (sanim->anim && use_proxy) { + seq_proxy_index_dir_set(sanim->anim, dir); + } } } - -static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char *name) +static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render_size, char *name, const size_t view_id) { int frameno; char dir[PROXY_MAXFILE]; + StripAnim *sanim; + char suffix[24] = {'\0'}; - if (!seq->strip->proxy) { + StripProxy *proxy = seq->strip->proxy; + if (!proxy) { return false; } @@ -1369,20 +1581,53 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * * have both, a directory full of jpeg files and proxy avis, so * sorry folks, please rebuild your proxies... */ - if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR | SEQ_USE_PROXY_CUSTOM_FILE)) { + sanim = BLI_findlink(&seq->anims, view_id); + + if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { + char fname[FILE_MAXFILE]; + if (ed->proxy_dir[0] == 0) + BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); + else + BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); + + if (sanim && sanim->anim) { + IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE); + } + else if (seq->type == SEQ_TYPE_IMAGE) { + fname[0] = 0; + } + BLI_path_append(dir, sizeof(dir), fname); + BLI_path_abs(name, G.main->name); + } + else if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE)) { BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); } + else if (sanim && sanim->anim && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)) { + char fname[FILE_MAXFILE]; + BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE); + BLI_path_append(dir, sizeof(dir), fname); + } else if (seq->type == SEQ_TYPE_IMAGE) { - BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir); + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) + BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + else + BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir); } else { return false; } - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + if (view_id > 0) + BLI_snprintf(suffix, sizeof(suffix), "_%zu", view_id); + + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && sanim && sanim->anim && + ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE) + { BLI_join_dirfile(name, PROXY_MAXFILE, - dir, seq->strip->proxy->file); + dir, proxy->file); BLI_path_abs(name, G.main->name); + BLI_snprintf(name, PROXY_MAXFILE, "%s_%s", name, suffix); return true; } @@ -1390,13 +1635,13 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * /* generate a separate proxy directory for each preview size */ if (seq->type == SEQ_TYPE_IMAGE) { - BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir, render_size, - BKE_sequencer_give_stripelem(seq, cfra)->name); + BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy%s", dir, render_size, + BKE_sequencer_give_stripelem(seq, cfra)->name, suffix); frameno = 1; } else { frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; - BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, render_size); + BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, render_size, suffix); } BLI_path_abs(name, G.main->name); @@ -1413,45 +1658,48 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c IMB_Proxy_Size psize = seq_rendersize_to_proxysize(context->preview_render_size); int size_flags; int render_size = context->preview_render_size; + StripProxy *proxy = seq->strip->proxy; + Editing *ed = context->scene->ed; + StripAnim *sanim; + + if (!(seq->flag & SEQ_USE_PROXY)) { + return NULL; + } /* dirty hack to distinguish 100% render size from PROXY_100 */ if (render_size == 99) { render_size = 100; } - if (!(seq->flag & SEQ_USE_PROXY)) { - return NULL; - } - - size_flags = seq->strip->proxy->build_size_flags; + size_flags = proxy->build_size_flags; /* only use proxies, if they are enabled (even if present!) */ if (psize == IMB_PROXY_NONE || ((size_flags & psize) != psize)) { return NULL; } - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; - if (seq->strip->proxy->anim == NULL) { - if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) { + if (proxy->anim == NULL) { + if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) { return NULL; } - /* proxies are generated in default color space */ - seq->strip->proxy->anim = openanim(name, IB_rect, 0, NULL); + proxy->anim = openanim(name, IB_rect, 0, seq->strip->colorspace_settings.name); } - if (seq->strip->proxy->anim == NULL) { + if (proxy->anim == NULL) { return NULL; } - seq_open_anim_file(seq); + seq_open_anim_file(context->scene, seq, true); + sanim = seq->anims.first; - frameno = IMB_anim_index_get_frame_index(seq->anim, seq->strip->proxy->tc, frameno); + frameno = IMB_anim_index_get_frame_index(sanim ? sanim->anim : NULL, seq->strip->proxy->tc, frameno); - return IMB_anim_absolute(seq->strip->proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); + return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); } - if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) { + if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) { return NULL; } @@ -1468,31 +1716,44 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c } } -static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, int cfra, int proxy_render_size) +static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, int cfra, + int proxy_render_size, const bool overwrite) { char name[PROXY_MAXFILE]; int quality; int rectx, recty; int ok; - ImBuf *ibuf; + ImBuf *ibuf_tmp, *ibuf; + Editing *ed = context->scene->ed; - if (!seq_proxy_get_fname(seq, cfra, proxy_render_size, name)) { + if (!seq_proxy_get_fname(ed, seq, cfra, proxy_render_size, name, context->view_id)) { return; } - ibuf = seq_render_strip(context, seq, cfra); + if (!overwrite && BLI_exists(name)) { + return; + } + + ibuf_tmp = seq_render_strip(context, seq, cfra); - rectx = (proxy_render_size * ibuf->x) / 100; - recty = (proxy_render_size * ibuf->y) / 100; + rectx = (proxy_render_size * ibuf_tmp->x) / 100; + recty = (proxy_render_size * ibuf_tmp->y) / 100; - if (ibuf->x != rectx || ibuf->y != recty) { + if (ibuf_tmp->x != rectx || ibuf_tmp->y != recty) { + ibuf = IMB_dupImBuf(ibuf_tmp); + IMB_metadata_copy(ibuf, ibuf_tmp); + IMB_freeImBuf(ibuf_tmp); IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty); } + else { + ibuf = ibuf_tmp; + } /* depth = 32 is intentionally left in, otherwise ALPHA channels * won't work... */ quality = seq->strip->proxy->quality; - ibuf->ftype = JPG | quality; + ibuf->ftype = IMB_FTYPE_JPG; + ibuf->foptions.quality = quality; /* unsupported feature only confuses other s/w */ if (ibuf->planes == 32) @@ -1508,46 +1769,138 @@ static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, i IMB_freeImBuf(ibuf); } -SeqIndexBuildContext *BKE_sequencer_proxy_rebuild_context(Main *bmain, Scene *scene, Sequence *seq) +/* returns whether the file this context would read from even exist, if not, don't create the context +*/ +static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, const size_t view_id) +{ + if ((scene->r.scemode & R_MULTIVIEW) == 0) + return false; + + if ((seq->type == SEQ_TYPE_IMAGE) && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) { + static char prefix[FILE_MAX]; + static const char *ext = NULL; + char str[FILE_MAX]; + + if (view_id == 0) { + char path[FILE_MAX]; + BLI_join_dirfile(path, sizeof(path), seq->strip->dir, + seq->strip->stripdata->name); + BLI_path_abs(path, G.main->name); + BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); + } + else { + prefix[0] = '\0'; + } + + if (prefix[0] == '\0') + return view_id != 0; + + seq_multiview_name(scene, view_id, prefix, ext, str, FILE_MAX); + + if (BLI_access(str, R_OK) == 0) + return false; + else + return view_id != 0; + } + return false; +} + +/** This returns the maximum possible number of required contexts +*/ +static size_t seq_proxy_context_count(Sequence *seq, Scene *scene) +{ + size_t num_views = 1; + + if ((scene->r.scemode & R_MULTIVIEW) == 0) + return 1; + + switch (seq->type) { + case SEQ_TYPE_MOVIE: + { + num_views = BLI_listbase_count(&seq->anims); + break; + } + case SEQ_TYPE_IMAGE: + { + switch (seq->views_format) { + case R_IMF_VIEWS_INDIVIDUAL: + num_views = BKE_scene_multiview_num_views_get(&scene->r); + break; + case R_IMF_VIEWS_STEREO_3D: + num_views = 2; + break; + case R_IMF_VIEWS_MULTIVIEW: + /* not supported at the moment */ + /* pass through */ + default: + num_views = 1; + } + break; + } + } + + return num_views; +} + +void BKE_sequencer_proxy_rebuild_context(Main *bmain, Scene *scene, Sequence *seq, struct GSet *file_list, ListBase *queue) { SeqIndexBuildContext *context; Sequence *nseq; + LinkData *link; + size_t i; + size_t num_files; if (!seq->strip || !seq->strip->proxy) { - return NULL; + return; } if (!(seq->flag & SEQ_USE_PROXY)) { - return NULL; + return; } - context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context"); + num_files = seq_proxy_context_count(seq, scene); + + for (i = 0; i < num_files; i++) { + if (seq_proxy_multiview_context_invalid(seq, scene, i)) + continue; - nseq = BKE_sequence_dupli_recursive(scene, scene, seq, 0); + context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context"); - context->tc_flags = nseq->strip->proxy->build_tc_flags; - context->size_flags = nseq->strip->proxy->build_size_flags; - context->quality = nseq->strip->proxy->quality; + nseq = BKE_sequence_dupli_recursive(scene, scene, seq, 0); - context->bmain = bmain; - context->scene = scene; - context->orig_seq = seq; - context->seq = nseq; + context->tc_flags = nseq->strip->proxy->build_tc_flags; + context->size_flags = nseq->strip->proxy->build_size_flags; + context->quality = nseq->strip->proxy->quality; + context->overwrite = (nseq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) == 0; - if (nseq->type == SEQ_TYPE_MOVIE) { - seq_open_anim_file(nseq); + context->bmain = bmain; + context->scene = scene; + context->orig_seq = seq; + context->seq = nseq; - if (nseq->anim) { - context->index_context = IMB_anim_index_rebuild_context(nseq->anim, - context->tc_flags, context->size_flags, context->quality); + context->view_id = i; /* only for images */ + + link = BLI_genericNodeN(context); + BLI_addtail(queue, link); + + if (nseq->type == SEQ_TYPE_MOVIE) { + StripAnim *sanim; + + seq_open_anim_file(scene, nseq, true); + sanim = BLI_findlink(&nseq->anims, i); + + if (sanim->anim) { + context->index_context = IMB_anim_index_rebuild_context(sanim->anim, + context->tc_flags, context->size_flags, context->quality, + context->overwrite, file_list); + } } } - - return context; } void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, short *do_update, float *progress) { + const bool overwrite = context->overwrite; SeqRenderData render_context; Sequence *seq = context->seq; Scene *scene = context->scene; @@ -1567,30 +1920,34 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho } /* that's why it is called custom... */ - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + if (seq->strip->proxy && seq->strip->proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { return; } /* fail safe code */ - render_context = BKE_sequencer_new_render_data(bmain->eval_ctx, bmain, context->scene, - (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f, - (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100); + BKE_sequencer_new_render_data( + bmain->eval_ctx, bmain, context->scene, + (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f, + (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100, + &render_context); + render_context.skip_cache = true; render_context.is_proxy_render = true; + render_context.view_id = context->view_id; for (cfra = seq->startdisp + seq->startstill; cfra < seq->enddisp - seq->endstill; cfra++) { if (context->size_flags & IMB_PROXY_25) { - seq_proxy_build_frame(&render_context, seq, cfra, 25); + seq_proxy_build_frame(&render_context, seq, cfra, 25, overwrite); } if (context->size_flags & IMB_PROXY_50) { - seq_proxy_build_frame(&render_context, seq, cfra, 50); + seq_proxy_build_frame(&render_context, seq, cfra, 50, overwrite); } if (context->size_flags & IMB_PROXY_75) { - seq_proxy_build_frame(&render_context, seq, cfra, 75); + seq_proxy_build_frame(&render_context, seq, cfra, 75, overwrite); } if (context->size_flags & IMB_PROXY_100) { - seq_proxy_build_frame(&render_context, seq, cfra, 100); + seq_proxy_build_frame(&render_context, seq, cfra, 100, overwrite); } *progress = (float) (cfra - seq->startdisp - seq->startstill) / (seq->enddisp - seq->endstill - seq->startdisp - seq->startstill); @@ -1604,8 +1961,14 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop) { if (context->index_context) { - IMB_close_anim_proxies(context->seq->anim); - IMB_close_anim_proxies(context->orig_seq->anim); + StripAnim *sanim; + + for (sanim = context->seq->anims.first; sanim; sanim = sanim->next) + IMB_close_anim_proxies(sanim->anim); + + for (sanim = context->orig_seq->anims.first; sanim; sanim = sanim->next) + IMB_close_anim_proxies(sanim->anim); + IMB_anim_index_rebuild_finish(context->index_context, stop); } @@ -1614,6 +1977,22 @@ void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop MEM_freeN(context); } +void BKE_sequencer_proxy_set(struct Sequence *seq, bool value) +{ + if (value) { + seq->flag |= SEQ_USE_PROXY; + if (seq->strip->proxy == NULL) { + seq->strip->proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy"); + seq->strip->proxy->quality = 90; + seq->strip->proxy->build_tc_flags = SEQ_PROXY_TC_ALL; + seq->strip->proxy->build_size_flags = SEQ_PROXY_IMAGE_SIZE_25; + } + } + else { + seq->flag ^= SEQ_USE_PROXY; + } +} + /*********************** color balance *************************/ static StripColorBalance calc_cb(StripColorBalance *cb_) @@ -1868,7 +2247,10 @@ static void *color_balance_do_thread(void *thread_data_v) return NULL; } -ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id, int cfra, bool make_float) +/* cfra is offset by fra_offset only in case we are using a real mask. */ +ImBuf *BKE_sequencer_render_mask_input( + const SeqRenderData *context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id, + int cfra, int fra_offset, bool make_float) { ImBuf *mask_input = NULL; @@ -1887,7 +2269,7 @@ ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, int mask_in } } else if (mask_input_type == SEQUENCE_MASK_INPUT_ID) { - mask_input = seq_render_mask(context, mask_id, cfra, make_float); + mask_input = seq_render_mask(context, mask_id, cfra - fra_offset, make_float); } return mask_input; @@ -2047,6 +2429,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); sequencer_imbuf_assign_spaces(scene, i); + IMB_metadata_copy(i, ibuf); IMB_freeImBuf(ibuf); ibuf = i; @@ -2098,6 +2481,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra); if (ibuf_new != ibuf) { + IMB_metadata_copy(ibuf_new, ibuf); IMB_freeImBuf(ibuf); ibuf = ibuf_new; } @@ -2120,6 +2504,7 @@ static ImBuf *copy_from_ibuf_still(const SeqRenderData *context, Sequence *seq, if (ibuf) { rval = IMB_dupImBuf(ibuf); + IMB_metadata_copy(rval, ibuf); IMB_freeImBuf(ibuf); } @@ -2133,9 +2518,11 @@ static void copy_to_ibuf_still(const SeqRenderData *context, Sequence *seq, floa /* we have to store a copy, since the passed ibuf * could be preprocessed afterwards (thereby silently * changing the cached image... */ - ibuf = IMB_dupImBuf(ibuf); + ImBuf *oibuf = ibuf; + ibuf = IMB_dupImBuf(oibuf); if (ibuf) { + IMB_metadata_copy(ibuf, oibuf); sequencer_imbuf_assign_spaces(context->scene, ibuf); } @@ -2331,6 +2718,237 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, Sequenc return out; } +static ImBuf *seq_render_image_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra) +{ + ImBuf *ibuf = NULL; + char name[FILE_MAX]; + bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && + (context->scene->r.scemode & R_MULTIVIEW) != 0; + StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); + int flag; + + if (s_elem) { + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); + BLI_path_abs(name, G.main->name); + } + + flag = IB_rect | IB_metadata; + if (seq->alpha_mode == SEQ_ALPHA_PREMUL) + flag |= IB_alphamode_premul; + + if (!s_elem) { + /* don't do anything */ + } + else if (is_multiview) { + size_t totfiles = seq_num_files(context->scene, seq->views_format, true); + size_t totviews; + struct ImBuf **ibufs_arr; + char prefix[FILE_MAX]; + const char *ext = NULL; + int i; + + if (totfiles > 1) { + BKE_scene_multiview_view_prefix_get(context->scene, name, prefix, &ext); + if (prefix[0] == '\0') { + goto monoview_image; + } + } + else { + prefix[0] = '\0'; + } + + totviews = BKE_scene_multiview_num_views_get(&context->scene->r); + ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"); + + for (i = 0; i < totfiles; i++) { + + if (prefix[0] == '\0') { + ibufs_arr[i] = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name); + } + else { + char str[FILE_MAX]; + seq_multiview_name(context->scene, i, prefix, ext, str, FILE_MAX); + ibufs_arr[i] = IMB_loadiffname(str, flag, seq->strip->colorspace_settings.name); + } + + if (ibufs_arr[i]) { + /* we don't need both (speed reasons)! */ + if (ibufs_arr[i]->rect_float && ibufs_arr[i]->rect) + imb_freerectImBuf(ibufs_arr[i]); + } + } + + if (seq->views_format == R_IMF_VIEWS_STEREO_3D && ibufs_arr[0]) + IMB_ImBufFromStereo3d(seq->stereo3d_format, ibufs_arr[0], &ibufs_arr[0], &ibufs_arr[1]); + + for (i = 0; i < totviews; i++) { + if (ibufs_arr[i]) { + SeqRenderData localcontext = *context; + localcontext.view_id = i; + + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibufs_arr[i], false); + + if (i != context->view_id) { + copy_to_ibuf_still(&localcontext, seq, nr, ibufs_arr[i]); + BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibufs_arr[i]); + } + } + } + + /* return the original requested ImBuf */ + ibuf = ibufs_arr[context->view_id]; + if (ibuf) { + s_elem->orig_width = ibufs_arr[0]->x; + s_elem->orig_height = ibufs_arr[0]->y; + } + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibufs_arr[i] != ibuf) { + IMB_freeImBuf(ibufs_arr[i]); + } + } + + MEM_freeN(ibufs_arr); + } + else { +monoview_image: + if ((ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) { + /* we don't need both (speed reasons)! */ + if (ibuf->rect_float && ibuf->rect) + imb_freerectImBuf(ibuf); + + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); + + s_elem->orig_width = ibuf->x; + s_elem->orig_height = ibuf->y; + } + } + + return ibuf; +} + +static ImBuf *seq_render_movie_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra) +{ + ImBuf *ibuf = NULL; + StripAnim *sanim; + bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && + (context->scene->r.scemode & R_MULTIVIEW) != 0; + + /* load all the videos */ + seq_open_anim_file(context->scene, seq, false); + + if (is_multiview) { + ImBuf **ibuf_arr; + size_t totviews; + size_t totfiles = seq_num_files(context->scene, seq->views_format, true); + int i; + + if (totfiles != BLI_listbase_count_ex(&seq->anims, totfiles + 1)) + goto monoview_movie; + + totviews = BKE_scene_multiview_num_views_get(&context->scene->r); + ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"); + + for (i = 0, sanim = seq->anims.first; sanim; sanim = sanim->next, i++) { + if (sanim->anim) { + IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size); + IMB_anim_set_preseek(sanim->anim, seq->anim_preseek); + + ibuf_arr[i] = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + proxy_size); + + /* fetching for requested proxy size failed, try fetching the original instead */ + if (!ibuf_arr[i] && proxy_size != IMB_PROXY_NONE) { + ibuf_arr[i] = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + IMB_PROXY_NONE); + } + if (ibuf_arr[i]) { + /* we don't need both (speed reasons)! */ + if (ibuf_arr[i]->rect_float && ibuf_arr[i]->rect) + imb_freerectImBuf(ibuf_arr[i]); + } + } + } + + if (seq->views_format == R_IMF_VIEWS_STEREO_3D) { + if (ibuf_arr[0]) { + IMB_ImBufFromStereo3d(seq->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); + } + else { + /* probably proxy hasn't been created yet */ + MEM_freeN(ibuf_arr); + return NULL; + } + } + + for (i = 0; i < totviews; i++) { + SeqRenderData localcontext = *context; + localcontext.view_id = i; + + if (ibuf_arr[i]) { + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf_arr[i], false); + } + if (i != context->view_id) { + copy_to_ibuf_still(&localcontext, seq, nr, ibuf_arr[i]); + BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf_arr[i]); + } + } + + /* return the original requested ImBuf */ + ibuf = ibuf_arr[context->view_id]; + if (ibuf) { + seq->strip->stripdata->orig_width = ibuf->x; + seq->strip->stripdata->orig_height = ibuf->y; + } + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibuf_arr[i] != ibuf) { + IMB_freeImBuf(ibuf_arr[i]); + } + } + + MEM_freeN(ibuf_arr); + } + else { +monoview_movie: + sanim = seq->anims.first; + if (sanim && sanim->anim) { + IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size); + IMB_anim_set_preseek(sanim->anim, seq->anim_preseek); + + ibuf = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + proxy_size); + + /* fetching for requested proxy size failed, try fetching the original instead */ + if (!ibuf && proxy_size != IMB_PROXY_NONE) { + ibuf = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + IMB_PROXY_NONE); + } + if (ibuf) { + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); + + /* we don't need both (speed reasons)! */ + if (ibuf->rect_float && ibuf->rect) { + imb_freerectImBuf(ibuf); + } + + seq->strip->stripdata->orig_width = ibuf->x; + seq->strip->stripdata->orig_height = ibuf->y; + } + } + } + return ibuf; +} + static ImBuf *seq_render_movieclip_strip(const SeqRenderData *context, Sequence *seq, float nr) { ImBuf *ibuf = NULL; @@ -2462,13 +3080,20 @@ static ImBuf *seq_render_mask_strip(const SeqRenderData *context, Sequence *seq, return seq_render_mask(context, seq->mask, nr, make_float); } -static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq, float nr) +static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra) { ImBuf *ibuf = NULL; - float frame; - float oldcfra; + double frame; Object *camera; - ListBase oldmarkers; + + struct { + int scemode; + int cfra; + float subframe; +#ifdef DURIAN_CAMERA_SWITCH + ListBase markers; +#endif + } orig_data; /* Old info: * Hack! This function can be called from do_render_seq(), in that case @@ -2506,9 +3131,11 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq const bool do_seq_gl = is_rendering ? 0 /* (context->scene->r.seq_flag & R_SEQ_GL_REND) */ : (context->scene->r.seq_flag & R_SEQ_GL_PREV) != 0; - int do_seq; // bool have_seq = false; /* UNUSED */ bool have_comp = false; + bool use_gpencil = true; + /* do we need to re-evaluate the frame after rendering? */ + bool is_frame_update = false; Scene *scene; int is_thread_main = BLI_thread_is_main(); @@ -2518,13 +3145,19 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq } scene = seq->scene; - frame = scene->r.sfra + nr + seq->anim_startofs; + frame = (double)scene->r.sfra + (double)nr + (double)seq->anim_startofs; // have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first); /* UNUSED */ have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree; - oldcfra = scene->r.cfra; - scene->r.cfra = frame; + orig_data.scemode = scene->r.scemode; + orig_data.cfra = scene->r.cfra; + orig_data.subframe = scene->r.subframe; +#ifdef DURIAN_CAMERA_SWITCH + orig_data.markers = scene->markers; +#endif + + BKE_scene_frame_set(scene, frame); if (seq->scene_camera) { camera = seq->scene_camera; @@ -2533,28 +3166,30 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq BKE_scene_camera_switch_update(scene); camera = scene->camera; } - + if (have_comp == false && camera == NULL) { - scene->r.cfra = oldcfra; - return NULL; + goto finally; + } + + if (seq->flag & SEQ_SCENE_NO_GPENCIL) { + use_gpencil = false; } /* prevent eternal loop */ - do_seq = scene->r.scemode & R_DOSEQ; scene->r.scemode &= ~R_DOSEQ; #ifdef DURIAN_CAMERA_SWITCH /* stooping to new low's in hackyness :( */ - oldmarkers = scene->markers; BLI_listbase_clear(&scene->markers); -#else - (void)oldmarkers; #endif + is_frame_update = (orig_data.cfra != scene->r.cfra) || (orig_data.subframe != scene->r.subframe); + if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) { char err_out[256] = "unknown"; int width = (scene->r.xsch * scene->r.size) / 100; int height = (scene->r.ysch * scene->r.size) / 100; + const char *viewname = BKE_scene_multiview_render_view_name_get(&scene->r, context->view_id); /* for old scened this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ @@ -2566,14 +3201,18 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq ibuf = sequencer_view3d_cb(scene, camera, width, height, IB_rect, context->scene->r.seq_prev_type, (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0, - true, scene->r.alphamode, err_out); + use_gpencil, true, scene->r.alphamode, viewname, err_out); if (ibuf == NULL) { fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out); } } else { Render *re = RE_GetRender(scene->id.name); - RenderResult rres; + size_t totviews = BKE_scene_multiview_num_views_get(&scene->r); + int i; + ImBuf **ibufs_arr; + + ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"); /* XXX: this if can be removed when sequence preview rendering uses the job system * @@ -2583,7 +3222,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq * When rendering from command line renderer is called from main thread, in this * case it's always safe to render scene here */ - if (!is_thread_main || is_rendering == false || is_background) { + if (!is_thread_main || is_rendering == false || is_background || context->eval_ctx->mode == DAG_EVAL_RENDER) { if (re == NULL) re = RE_NewRender(scene->id.name); @@ -2593,42 +3232,68 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq /* restore previous state after it was toggled on & off by RE_BlenderFrame */ G.is_rendering = is_rendering; } - - RE_AcquireResultImage(re, &rres); - - if (rres.rectf) { - ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat); - memcpy(ibuf->rect_float, rres.rectf, 4 * sizeof(float) * rres.rectx * rres.recty); - if (rres.rectz) { - addzbuffloatImBuf(ibuf); - memcpy(ibuf->zbuf_float, rres.rectz, sizeof(float) * rres.rectx * rres.recty); + + for (i = 0; i < totviews; i++) { + SeqRenderData localcontext = *context; + RenderResult rres; + + localcontext.view_id = i; + + RE_AcquireResultImage(re, &rres, i); + + if (rres.rectf) { + ibufs_arr[i] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat); + memcpy(ibufs_arr[i]->rect_float, rres.rectf, 4 * sizeof(float) * rres.rectx * rres.recty); + + if (rres.rectz) { + addzbuffloatImBuf(ibufs_arr[i]); + memcpy(ibufs_arr[i]->zbuf_float, rres.rectz, sizeof(float) * rres.rectx * rres.recty); + } + + /* float buffers in the sequencer are not linear */ + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibufs_arr[i], false); + } + else if (rres.rect32) { + ibufs_arr[i] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect); + memcpy(ibufs_arr[i]->rect, rres.rect32, 4 * rres.rectx * rres.recty); } - /* float buffers in the sequencer are not linear */ - BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); + if (i != context->view_id) { + copy_to_ibuf_still(&localcontext, seq, nr, ibufs_arr[i]); + BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibufs_arr[i]); + } + + RE_ReleaseResultImage(re); } - else if (rres.rect32) { - ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect); - memcpy(ibuf->rect, rres.rect32, 4 * rres.rectx * rres.recty); + + /* return the original requested ImBuf */ + ibuf = ibufs_arr[context->view_id]; + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibufs_arr[i] != ibuf) { + IMB_freeImBuf(ibufs_arr[i]); + } } - - RE_ReleaseResultImage(re); - + MEM_freeN(ibufs_arr); + // BIF_end_render_callbacks(); } - + + +finally: /* restore */ - scene->r.scemode |= do_seq; - - scene->r.cfra = oldcfra; + scene->r.scemode = orig_data.scemode; + scene->r.cfra = orig_data.cfra; + scene->r.subframe = orig_data.subframe; - if (frame != oldcfra) { + if (is_frame_update) { BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay); } - + #ifdef DURIAN_CAMERA_SWITCH /* stooping to new low's in hackyness :( */ - scene->markers = oldmarkers; + scene->markers = orig_data.markers; #endif return ibuf; @@ -2640,7 +3305,6 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s float nr = give_stripelem_index(seq, cfra); int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type; bool use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); - char name[FILE_MAX]; switch (type) { case SEQ_TYPE_META: @@ -2699,57 +3363,14 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s case SEQ_TYPE_IMAGE: { - StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); - int flag; - - if (s_elem) { - BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); - BLI_path_abs(name, G.main->name); - } - - flag = IB_rect; - if (seq->alpha_mode == SEQ_ALPHA_PREMUL) - flag |= IB_alphamode_premul; - - if (s_elem && (ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) { - /* we don't need both (speed reasons)! */ - if (ibuf->rect_float && ibuf->rect) - imb_freerectImBuf(ibuf); - - /* all sequencer color is done in SRGB space, linear gives odd crossfades */ - BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); - - copy_to_ibuf_still(context, seq, nr, ibuf); - - s_elem->orig_width = ibuf->x; - s_elem->orig_height = ibuf->y; - } + ibuf = seq_render_image_strip(context, seq, nr, cfra); + copy_to_ibuf_still(context, seq, nr, ibuf); break; } case SEQ_TYPE_MOVIE: { - seq_open_anim_file(seq); - - if (seq->anim) { - IMB_anim_set_preseek(seq->anim, seq->anim_preseek); - - ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs, - seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, - seq_rendersize_to_proxysize(context->preview_render_size)); - - if (ibuf) { - BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); - - /* we don't need both (speed reasons)! */ - if (ibuf->rect_float && ibuf->rect) { - imb_freerectImBuf(ibuf); - } - - seq->strip->stripdata->orig_width = ibuf->x; - seq->strip->stripdata->orig_height = ibuf->y; - } - } + ibuf = seq_render_movie_strip(context, seq, nr, cfra); copy_to_ibuf_still(context, seq, nr, ibuf); break; } @@ -2757,7 +3378,7 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s case SEQ_TYPE_SCENE: { /* scene can be NULL after deletions */ - ibuf = seq_render_scene_strip(context, seq, nr); + ibuf = seq_render_scene_strip(context, seq, nr, cfra); /* Scene strips update all animation, so we need to restore original state.*/ BKE_animsys_evaluate_all_animation(context->bmain, context->scene, cfra); @@ -2986,6 +3607,8 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2); + IMB_metadata_copy(out, ibuf2); + IMB_freeImBuf(ibuf1); IMB_freeImBuf(ibuf2); } @@ -3080,7 +3703,7 @@ ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int cha if (ed == NULL) return NULL; if ((chanshown < 0) && !BLI_listbase_is_empty(&ed->metastack)) { - int count = BLI_countlist(&ed->metastack); + int count = BLI_listbase_count(&ed->metastack); count = max_ii(count + chanshown, 0); seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep; } @@ -3254,16 +3877,6 @@ ImBuf *BKE_sequencer_give_ibuf_threaded(const SeqRenderData *context, float cfra return e ? e->ibuf : NULL; } -/* Functions to free imbuf and anim data on changes */ - -static void free_anim_seq(Sequence *seq) -{ - if (seq->anim) { - IMB_free_anim(seq->anim); - seq->anim = NULL; - } -} - /* check whether sequence cur depends on seq */ bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur) { @@ -3315,15 +3928,11 @@ static void sequence_invalidate_cache(Scene *scene, Sequence *seq, bool invalida /* invalidate cache for current sequence */ if (invalidate_self) { - if (seq->anim) { - /* Animation structure holds some buffers inside, - * so for proper cache invalidation we need to - * re-open the animation. - */ - IMB_free_anim(seq->anim); - seq->anim = NULL; - } - + /* Animation structure holds some buffers inside, + * so for proper cache invalidation we need to + * re-open the animation. + */ + BKE_sequence_free_anim(seq); BKE_sequencer_cache_cleanup_sequence(seq); } @@ -3370,7 +3979,7 @@ void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) if (seq->strip) { if (seq->type == SEQ_TYPE_MOVIE) { - free_anim_seq(seq); + BKE_sequence_free_anim(seq); } if (seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, true); @@ -3395,7 +4004,7 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha /* recurs downwards to see if this seq depends on the changed seq */ if (seq == NULL) - return 0; + return false; if (seq == changed_seq) free_imbuf = true; @@ -3417,7 +4026,7 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha if (free_imbuf) { if (ibuf_change) { if (seq->type == SEQ_TYPE_MOVIE) - free_anim_seq(seq); + BKE_sequence_free_anim(seq); if (seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, true); } @@ -3513,28 +4122,16 @@ bool BKE_sequence_single_check(Sequence *seq) } /* check if the selected seq's reference unselected seq's */ -bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase, bool one_only) +bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase) { Sequence *seq; - /* is there a valid selection select */ + /* is there more than 1 select */ bool ok = false; - /* is there one selected already? */ - bool first = false; for (seq = seqbase->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - if (one_only) { - ok = true; - break; - } - else { - if (first) { - ok = true; - break; - } - else - first = true; - } + ok = true; + break; } } @@ -3632,7 +4229,7 @@ void BKE_sequence_single_fix(Sequence *seq) bool BKE_sequence_tx_test(Sequence *seq) { - return (seq->type < SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0); + return !(seq->type & SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0); } static bool seq_overlap(Sequence *seq1, Sequence *seq2) @@ -3681,10 +4278,10 @@ void BKE_sequence_sound_init(Scene *scene, Sequence *seq) } else { if (seq->sound) { - seq->scene_sound = sound_add_scene_sound_defaults(scene, seq); + seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq); } if (seq->scene) { - seq->scene_sound = sound_scene_add_scene_sound_defaults(scene, seq); + seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene, seq); } } } @@ -3712,21 +4309,23 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame) } /* return 0 if there werent enough space */ -bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene) +bool BKE_sequence_base_shuffle_ex(ListBase *seqbasep, Sequence *test, Scene *evil_scene, int channel_delta) { - int orig_machine = test->machine; - test->machine++; + const int orig_machine = test->machine; + BLI_assert(ELEM(channel_delta, -1, 1)); + + test->machine += channel_delta; BKE_sequence_calc(evil_scene, test); - while (BKE_sequence_test_overlap(seqbasep, test) ) { - if (test->machine >= MAXSEQ) { + while (BKE_sequence_test_overlap(seqbasep, test)) { + if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine <= 1)) { break; } - test->machine++; + + test->machine += channel_delta; BKE_sequence_calc(evil_scene, test); // XXX - I don't think this is needed since were only moving vertically, Campbell. } - - if (test->machine >= MAXSEQ) { + if ((test->machine < 1) || (test->machine > MAXSEQ)) { /* Blender 2.4x would remove the strip. * nicer to move it to the end */ @@ -3750,6 +4349,11 @@ bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_s } } +bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene) +{ + return BKE_sequence_base_shuffle_ex(seqbasep, test, evil_scene, 1); +} + static int shuffle_seq_time_offset_test(ListBase *seqbasep, char dir) { int offset = 0; @@ -3889,11 +4493,11 @@ void BKE_sequencer_update_sound_bounds(Scene *scene, Sequence *seq) /* We have to take into account start frame of the sequence's scene! */ int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra; - sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs); + BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs); } } else { - sound_move_scene_sound_defaults(scene, seq); + BKE_sound_move_scene_sound_defaults(scene, seq); } /* mute is set in seq_update_muting_recursive */ } @@ -3918,7 +4522,7 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i } else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { if (seq->scene_sound) { - sound_mute_scene_sound(seq->scene_sound, seqmute); + BKE_sound_mute_scene_sound(seq->scene_sound, seqmute); } } } @@ -3947,7 +4551,7 @@ static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound } else if (seq->type == SEQ_TYPE_SOUND_RAM) { if (seq->scene_sound && sound == seq->sound) { - sound_update_scene_sound(seq->scene_sound, sound); + BKE_sound_update_scene_sound(seq->scene_sound, sound); } } } @@ -4062,7 +4666,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char char name_esc[SEQ_NAME_MAXSTR * 2]; BLI_strescape(name_esc, name, sizeof(name_esc)); - return BLI_snprintf(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); + return BLI_snprintf_rlen(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); } /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ @@ -4280,7 +4884,7 @@ static void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) { if (seq->sound) - sound_cache(seq->sound); + BKE_sound_cache(seq->sound); } seq_load->tot_success++; @@ -4310,6 +4914,8 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine) seq->pitch = 1.0f; seq->scene_sound = NULL; + seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format"); + return seq; } @@ -4367,6 +4973,12 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad strip->stripdata = MEM_callocN(seq->len * sizeof(StripElem), "stripelem"); BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir)); + if (seq_load->stereo3d_format) + *seq->stereo3d_format = *seq_load->stereo3d_format; + + seq->views_format = seq_load->views_format; + seq->flag |= seq_load->flag & SEQ_USE_VIEWS; + seq_load_apply(scene, seq, seq_load); return seq; @@ -4386,9 +4998,9 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad AUD_SoundInfo info; - sound = sound_new_file(bmain, seq_load->path); /* handles relative paths */ + sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ - if (sound == NULL || sound->playback_handle == NULL) { + if (sound->playback_handle == NULL) { #if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); @@ -4400,7 +5012,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad info = AUD_getInfo(sound->playback_handle); if (info.specs.channels == AUD_CHANNELS_INVALID) { - sound_delete(bmain, sound); + BKE_sound_delete(bmain, sound); #if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); @@ -4425,7 +5037,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - seq->scene_sound = sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0); + seq->scene_sound = BKE_sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0); BKE_sequence_calc_disp(scene, seq); @@ -4446,6 +5058,12 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad } #endif // WITH_AUDASPACE +static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const size_t view_id) +{ + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id); + IMB_suffix_anim(anim, suffix); +} + Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) { Scene *scene = CTX_data_scene(C); /* only for sound */ @@ -4455,29 +5073,84 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad Strip *strip; StripElem *se; char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */ - - struct anim *an; + bool is_multiview_loaded = false; + const bool is_multiview = (seq_load->flag & SEQ_USE_VIEWS) != 0; + size_t totfiles = seq_num_files(scene, seq_load->views_format, is_multiview); + struct anim **anim_arr; + int i; BLI_strncpy(path, seq_load->path, sizeof(path)); BLI_path_abs(path, G.main->name); - an = openanim(path, IB_rect, 0, colorspace); + anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files"); - if (an == NULL) - return NULL; + if (is_multiview && (seq_load->views_format == R_IMF_VIEWS_INDIVIDUAL)) { + char prefix[FILE_MAX]; + const char *ext = NULL; + size_t j = 0; + + BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); + + if (prefix[0] != '\0') { + for (i = 0; i < totfiles; i++) { + char str[FILE_MAX]; + + seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); + anim_arr[j] = openanim(str, IB_rect, 0, colorspace); + + if (anim_arr[j]) { + seq_anim_add_suffix(scene, anim_arr[j], i); + j++; + } + } + + if (j == 0) { + MEM_freeN(anim_arr); + return NULL; + } + is_multiview_loaded = true; + } + } + + if (is_multiview_loaded == false) { + anim_arr[0] = openanim(path, IB_rect, 0, colorspace); + + if (anim_arr[0] == NULL) { + MEM_freeN(anim_arr); + return NULL; + } + } seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel); + + /* multiview settings */ + if (seq_load->stereo3d_format) { + *seq->stereo3d_format = *seq_load->stereo3d_format; + seq->views_format = seq_load->views_format; + } + seq->flag |= seq_load->flag & SEQ_USE_VIEWS; + seq->type = SEQ_TYPE_MOVIE; seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ - seq->anim = an; - seq->anim_preseek = IMB_anim_get_preseek(an); + for (i = 0; i < totfiles; i++) { + if (anim_arr[i]) { + StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); + sanim->anim = anim_arr[i]; + } + else { + break; + } + } + + 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); /* basic defaults */ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); - seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN); + seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN); strip->us = 1; BLI_strncpy(seq->strip->colorspace_settings.name, colorspace, sizeof(seq->strip->colorspace_settings.name)); @@ -4505,6 +5178,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad /* can be NULL */ seq_load_apply(scene, seq, seq_load); + MEM_freeN(anim_arr); return seq; } @@ -4516,6 +5190,8 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seq->tmp = seqn; seqn->strip = MEM_dupallocN(seq->strip); + seqn->stereo3d_format = MEM_dupallocN(seq->stereo3d_format); + /* XXX: add F-Curve duplication stuff? */ if (seq->strip->crop) { @@ -4531,6 +5207,10 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seqn->strip->proxy->anim = NULL; } + if (seq->prop) { + seqn->prop = IDP_CopyProperty(seq->prop); + } + if (seqn->modifiers.first) { BLI_listbase_clear(&seqn->modifiers); @@ -4547,7 +5227,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup else if (seq->type == SEQ_TYPE_SCENE) { seqn->strip->stripdata = NULL; if (seq->scene_sound) - seqn->scene_sound = sound_scene_add_scene_sound_defaults(sce_audio, seqn); + seqn->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce_audio, seqn); } else if (seq->type == SEQ_TYPE_MOVIECLIP) { /* avoid assert */ @@ -4558,13 +5238,13 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup else if (seq->type == SEQ_TYPE_MOVIE) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); - seqn->anim = NULL; + BLI_listbase_clear(&seqn->anims); } else if (seq->type == SEQ_TYPE_SOUND_RAM) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); if (seq->scene_sound) - seqn->scene_sound = sound_add_scene_sound_defaults(sce_audio, seqn); + seqn->scene_sound = BKE_sound_add_scene_sound_defaults(sce_audio, seqn); id_us_plus((ID *)seqn->sound); } @@ -4572,17 +5252,11 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); } - else if (seq->type >= SEQ_TYPE_EFFECT) { - if (seq->seq1 && seq->seq1->tmp) seqn->seq1 = seq->seq1->tmp; - if (seq->seq2 && seq->seq2->tmp) seqn->seq2 = seq->seq2->tmp; - if (seq->seq3 && seq->seq3->tmp) seqn->seq3 = seq->seq3->tmp; - - if (seq->type & SEQ_TYPE_EFFECT) { - struct SeqEffectHandle sh; - sh = BKE_sequence_get_effect(seq); - if (sh.copy) - sh.copy(seq, seqn); - } + else if (seq->type & SEQ_TYPE_EFFECT) { + struct SeqEffectHandle sh; + sh = BKE_sequence_get_effect(seq); + if (sh.copy) + sh.copy(seq, seqn); seqn->strip->stripdata = NULL; @@ -4601,9 +5275,34 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup return seqn; } +static void seq_new_fix_links_recursive(Sequence *seq) +{ + SequenceModifierData *smd; + + if (seq->type & SEQ_TYPE_EFFECT) { + if (seq->seq1 && seq->seq1->tmp) seq->seq1 = seq->seq1->tmp; + if (seq->seq2 && seq->seq2->tmp) seq->seq2 = seq->seq2->tmp; + if (seq->seq3 && seq->seq3->tmp) seq->seq3 = seq->seq3->tmp; + } + else if (seq->type == SEQ_TYPE_META) { + Sequence *seqn; + for (seqn = seq->seqbase.first; seqn; seqn = seqn->next) { + seq_new_fix_links_recursive(seqn); + } + } + + for (smd = seq->modifiers.first; smd; smd = smd->next) { + if (smd->mask_sequence && smd->mask_sequence->tmp) + smd->mask_sequence = smd->mask_sequence->tmp; + } +} + Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag) { - Sequence *seqn = seq_dupli(scene, scene_to, seq, dupe_flag); + Sequence *seqn; + + seq->tmp = NULL; + seqn = seq_dupli(scene, scene_to, seq, dupe_flag); if (seq->type == SEQ_TYPE_META) { Sequence *s; for (s = seq->seqbase.first; s; s = s->next) { @@ -4613,14 +5312,21 @@ Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence * } } } + + seq_new_fix_links_recursive(seqn); + return seqn; } -void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag) +void BKE_sequence_base_dupli_recursive( + Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, + int dupe_flag) { Sequence *seq; Sequence *seqn = NULL; Sequence *last_seq = BKE_sequencer_active_get(scene); + /* always include meta's strips */ + int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL; for (seq = seqbase->first; seq; seq = seq->next) { seq->tmp = NULL; @@ -4633,8 +5339,11 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase * } BLI_addtail(nseqbase, seqn); - if (seq->type == SEQ_TYPE_META) - BKE_sequence_base_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag); + if (seq->type == SEQ_TYPE_META) { + BKE_sequence_base_dupli_recursive( + scene, scene_to, &seqn->seqbase, &seq->seqbase, + dupe_flag_recursive); + } if (dupe_flag & SEQ_DUPE_CONTEXT) { if (seq == last_seq) { @@ -4644,6 +5353,11 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase * } } } + + /* fix modifier linking */ + for (seq = nseqbase->first; seq; seq = seq->next) { + seq_new_fix_links_recursive(seq); + } } /* called on draw, needs to be fast, @@ -4664,3 +5378,70 @@ bool BKE_sequence_is_valid_check(Sequence *seq) return true; } +int BKE_sequencer_find_next_prev_edit( + Scene *scene, int cfra, const short side, + const bool do_skip_mute, const bool do_center, const bool do_unselected) +{ + Editing *ed = BKE_sequencer_editing_get(scene, false); + Sequence *seq; + + int dist, best_dist, best_frame = cfra; + int seq_frames[2], seq_frames_tot; + + /* in case where both is passed, frame just finds the nearest end while frame_left the nearest start */ + + best_dist = MAXFRAME * 2; + + if (ed == NULL) return cfra; + + for (seq = ed->seqbasep->first; seq; seq = seq->next) { + int i; + + if (do_skip_mute && (seq->flag & SEQ_MUTE)) { + continue; + } + + if (do_unselected && (seq->flag & SELECT)) + continue; + + if (do_center) { + seq_frames[0] = (seq->startdisp + seq->enddisp) / 2; + seq_frames_tot = 1; + } + else { + seq_frames[0] = seq->startdisp; + seq_frames[1] = seq->enddisp; + + seq_frames_tot = 2; + } + + for (i = 0; i < seq_frames_tot; i++) { + const int seq_frame = seq_frames[i]; + + dist = MAXFRAME * 2; + + switch (side) { + case SEQ_SIDE_LEFT: + if (seq_frame < cfra) { + dist = cfra - seq_frame; + } + break; + case SEQ_SIDE_RIGHT: + if (seq_frame > cfra) { + dist = seq_frame - cfra; + } + break; + case SEQ_SIDE_BOTH: + dist = abs(seq_frame - cfra); + break; + } + + if (dist < best_dist) { + best_frame = seq_frame; + best_dist = dist; + } + } + } + + return best_frame; +} |