Merged changes in the trunk up to revision 55357.
[blender-staging.git] / source / blender / blenkernel / intern / movieclip.c
index 97d4c150b845565a2955851cda23250cf6a2d697..e79754ca203b9e26f97cc5cf30d2a632e618ebd1 100644 (file)
@@ -52,6 +52,7 @@
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
 #include "DNA_movieclip_types.h"
+#include "DNA_node_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_view3d_types.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_movieclip.h"
+#include "BKE_node.h"
 #include "BKE_image.h"  /* openanim */
 #include "BKE_tracking.h"
+#include "BKE_sequencer.h"
 
 #include "IMB_colormanagement.h"
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 #include "IMB_moviecache.h"
 
+#ifdef WITH_OPENEXR
+#include "intern/openexr/openexr_multi.h"
+#endif
+
 /*********************** movieclip buffer loaders *************************/
 
 static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
@@ -214,11 +221,20 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user,
                colorspace = clip->colorspace_settings.name;
        }
 
-       loadflag = IB_rect | IB_multilayer;
+       loadflag = IB_rect | IB_multilayer | IB_alphamode_detect;
 
        /* read ibuf */
        ibuf = IMB_loadiffname(name, loadflag, colorspace);
 
+#ifdef WITH_OPENEXR
+       if (ibuf) {
+               if (ibuf->ftype == OPENEXR && ibuf->userdata) {
+                       IMB_exr_close(ibuf->userdata);
+                       ibuf->userdata = NULL;
+               }
+       }
+#endif
+
        return ibuf;
 }
 
@@ -292,11 +308,11 @@ static void movieclip_calc_length(MovieClip *clip)
                        clip->len = framenr + 1;
                }
                else {
-                       for (;; ) {
+                       for (;;) {
                                get_sequence_fname(clip, framenr, name);
 
                                if (!BLI_exists(name)) {
-                                       clip->len = framenr + 1;
+                                       clip->len = framenr;
                                        break;
                                }
 
@@ -477,11 +493,11 @@ static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, i
 /*********************** common functions *************************/
 
 /* only image block itself */
-static MovieClip *movieclip_alloc(const char *name)
+static MovieClip *movieclip_alloc(Main *bmain, const char *name)
 {
        MovieClip *clip;
 
-       clip = BKE_libblock_alloc(&G.main->movieclip, ID_MC, name);
+       clip = BKE_libblock_alloc(&bmain->movieclip, ID_MC, name);
 
        clip->aspx = clip->aspy = 1.0f;
 
@@ -518,11 +534,29 @@ static void movieclip_load_get_szie(MovieClip *clip)
        }
 }
 
+static void detect_clip_source(MovieClip *clip)
+{
+       ImBuf *ibuf;
+       char name[FILE_MAX];
+
+       BLI_strncpy(name, clip->name, sizeof(name));
+       BLI_path_abs(name, G.main->name);
+
+       ibuf = IMB_testiffname(name, IB_rect | IB_multilayer);
+       if (ibuf) {
+               clip->source = MCLIP_SRC_SEQUENCE;
+               IMB_freeImBuf(ibuf);
+       }
+       else {
+               clip->source = MCLIP_SRC_MOVIE;
+       }
+}
+
 /* checks if image was already loaded, then returns same image
  * otherwise creates new.
  * does not load ibuf itself
  * pass on optional frame for #name images */
-MovieClip *BKE_movieclip_file_add(const char *name)
+MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
 {
        MovieClip *clip;
        int file, len;
@@ -530,7 +564,7 @@ MovieClip *BKE_movieclip_file_add(const char *name)
        char str[FILE_MAX], strtest[FILE_MAX];
 
        BLI_strncpy(str, name, sizeof(str));
-       BLI_path_abs(str, G.main->name);
+       BLI_path_abs(str, bmain->name);
 
        /* exists? */
        file = BLI_open(str, O_BINARY | O_RDONLY, 0);
@@ -539,7 +573,7 @@ MovieClip *BKE_movieclip_file_add(const char *name)
        close(file);
 
        /* ** first search an identical clip ** */
-       for (clip = G.main->movieclip.first; clip; clip = clip->id.next) {
+       for (clip = bmain->movieclip.first; clip; clip = clip->id.next) {
                BLI_strncpy(strtest, clip->name, sizeof(clip->name));
                BLI_path_abs(strtest, G.main->name);
 
@@ -560,13 +594,10 @@ MovieClip *BKE_movieclip_file_add(const char *name)
                len--;
        libname = name + len;
 
-       clip = movieclip_alloc(libname);
+       clip = movieclip_alloc(bmain, libname);
        BLI_strncpy(clip->name, name, sizeof(clip->name));
 
-       if (BLI_testextensie_array(name, imb_ext_movie))
-               clip->source = MCLIP_SRC_MOVIE;
-       else
-               clip->source = MCLIP_SRC_SEQUENCE;
+       detect_clip_source(clip);
 
        movieclip_load_get_szie(clip);
        if (clip->lastsize[0]) {
@@ -614,34 +645,27 @@ static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *dist
        else
                undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
 
-       if (undistibuf->userflags & IB_RECT_INVALID) {
-               ibuf->userflags &= ~IB_RECT_INVALID;
-               IMB_rect_from_float(undistibuf);
-       }
-
        IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y);
 
        return undistibuf;
 }
 
-static int need_undistortion_postprocess(MovieClipUser *user, int flag)
+static int need_undistortion_postprocess(MovieClipUser *user)
 {
        int result = 0;
 
        /* only full undistorted render can be used as on-fly undistorting image */
-       if (flag & MCLIP_USE_PROXY) {
-               result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) &&
-                         (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
-       }
+       result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) &&
+                 (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
 
        return result;
 }
 
-static int need_postprocessed_frame(MovieClipUser *user, int flag, int postprocess_flag)
+static int need_postprocessed_frame(MovieClipUser *user, int postprocess_flag)
 {
        int result = postprocess_flag;
 
-       result |= need_undistortion_postprocess(user, flag);
+       result |= need_undistortion_postprocess(user);
 
        return result;
 }
@@ -688,7 +712,7 @@ static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *use
        if (cache->postprocessed.flag != postprocess_flag)
                return NULL;
 
-       if (need_undistortion_postprocess(user, flag)) {
+       if (need_undistortion_postprocess(user)) {
                if (!check_undistortion_cache_flags(clip))
                        return NULL;
        }
@@ -719,7 +743,7 @@ static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *u
                cache->postprocessed.render_flag = 0;
        }
 
-       if (need_undistortion_postprocess(user, flag)) {
+       if (need_undistortion_postprocess(user)) {
                copy_v2_v2(cache->postprocessed.principal, camera->principal);
                copy_v3_v3(&cache->postprocessed.k1, &camera->k1);
                cache->postprocessed.undistortion_used = TRUE;
@@ -763,7 +787,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *u
        BLI_lock_thread(LOCK_MOVIECLIP);
 
        /* try to obtain cached postprocessed frame first */
-       if (need_postprocessed_frame(user, flag, postprocess_flag)) {
+       if (need_postprocessed_frame(user, postprocess_flag)) {
                ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
 
                if (!ibuf)
@@ -1087,15 +1111,24 @@ void BKE_movieclip_reload(MovieClip *clip)
        clip->tracking.stabilization.ok = FALSE;
 
        /* update clip source */
-       if (BLI_testextensie_array(clip->name, imb_ext_movie))
-               clip->source = MCLIP_SRC_MOVIE;
-       else
-               clip->source = MCLIP_SRC_SEQUENCE;
+       detect_clip_source(clip);
 
        clip->lastsize[0] = clip->lastsize[1] = 0;
        movieclip_load_get_szie(clip);
 
        movieclip_calc_length(clip);
+
+       /* same as for image update -- don't use notifiers because they are not 100% sure to succeeded
+        * (node trees which are not currently visible wouldn't be refreshed)
+        */
+       {
+               Scene *scene;
+               for (scene = G.main->scene.first; scene; scene = scene->id.next) {
+                       if (scene->nodetree) {
+                               nodeUpdateID(scene->nodetree, &clip->id);
+                       }
+               }
+       }
 }
 
 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
@@ -1157,13 +1190,16 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
 
                                        search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, TRUE, TRUE);
 
-                                       if (!search_ibuf->rect_float) {
-                                               /* sampling happens in float buffer */
-                                               IMB_float_from_rect(search_ibuf);
+                                       if (search_ibuf) {
+                                               if (!search_ibuf->rect_float) {
+                                                       /* sampling happens in float buffer */
+                                                       IMB_float_from_rect(search_ibuf);
+                                               }
+
+                                               scopes->track_search = search_ibuf;
                                        }
 
                                        scopes->undist_marker = undist_marker;
-                                       scopes->track_search = search_ibuf;
 
                                        scopes->frame_width = ibuf->x;
                                        scopes->frame_height = ibuf->y;
@@ -1194,7 +1230,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
        scopes->ok = TRUE;
 }
 
-static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted)
+static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted, bool threaded)
 {
        char name[FILE_MAX];
        int quality, rectx, recty;
@@ -1208,7 +1244,10 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
 
        scaleibuf = IMB_dupImBuf(ibuf);
 
-       IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
+       if (threaded)
+               IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty);
+       else
+               IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
 
        quality = clip->proxy.quality;
        scaleibuf->ftype = JPG | quality;
@@ -1217,6 +1256,10 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
        if (scaleibuf->planes == 32)
                scaleibuf->planes = 24;
 
+       /* TODO: currently the most weak part of multithreaded proxies,
+        *       could be solved in a way that thread only prepares memory
+        *       buffer and write to disk happens separately
+        */
        BLI_lock_thread(LOCK_MOVIECLIP);
 
        BLI_make_existing_file(name);
@@ -1228,12 +1271,18 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
        IMB_freeImBuf(scaleibuf);
 }
 
+/* note: currently used by proxy job for movies, threading happens within single frame
+ * (meaning scaling shall be threaded)
+ */
 void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
                                      int cfra, int *build_sizes, int build_count, int undistorted)
 {
        ImBuf *ibuf;
        MovieClipUser user;
 
+       if (!build_count)
+               return;
+
        user.framenr = cfra;
        user.render_flag = 0;
        user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
@@ -1248,7 +1297,7 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct Movi
                        tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
 
                for (i = 0; i < build_count; i++)
-                       movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted);
+                       movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true);
 
                IMB_freeImBuf(ibuf);
 
@@ -1257,8 +1306,34 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct Movi
        }
 }
 
+/* note: currently used by proxy job for sequences, threading happens within sequence
+ * (different threads handles different frames, no threading within frame is needed)
+ */
+void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, struct MovieDistortion *distortion,
+                                              int cfra, int *build_sizes, int build_count, int undistorted)
+{
+       if (!build_count)
+               return;
+
+       if (ibuf) {
+               ImBuf *tmpibuf = ibuf;
+               int i;
+
+               if (undistorted)
+                       tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
+
+               for (i = 0; i < build_count; i++)
+                       movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false);
+
+               if (tmpibuf != ibuf)
+                       IMB_freeImBuf(tmpibuf);
+       }
+}
+
 void BKE_movieclip_free(MovieClip *clip)
 {
+       BKE_sequencer_clear_movieclip_in_clipboard(clip);
+
        free_buffers(clip);
 
        BKE_tracking_free(&clip->tracking);
@@ -1303,7 +1378,7 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
                bConstraint *con;
 
                for (con = ob->constraints.first; con; con = con->next) {
-                       bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+                       bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 
                        if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
                                bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data;
@@ -1326,6 +1401,11 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
                }
        }
 
+       {
+               bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT);
+               treetype->foreach_nodetree(bmain, (void *)clip, &BKE_node_tree_unlink_id_cb);
+       }
+
        clip->id.us = 0;
 }
 
@@ -1338,3 +1418,14 @@ float BKE_movieclip_remap_clip_to_scene_frame(MovieClip *clip, float framenr)
 {
        return framenr + (float) clip->start_frame - 1.0f;
 }
+
+void BKE_movieclip_filename_for_frame(MovieClip *clip, int framenr, char *name)
+{
+       if (clip->source != MCLIP_SRC_MOVIE) {
+               get_sequence_fname(clip, framenr, name);
+       }
+       else {
+               BLI_strncpy(name, clip->name, FILE_MAX);
+               BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
+       }
+}