Blender V2.61 - r43446

movieclip.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2011 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Blender Foundation,
00022  *                 Sergey Sharybin
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <fcntl.h>
00035 
00036 #ifndef WIN32
00037 #include <unistd.h>
00038 #else
00039 #include <io.h>
00040 #endif
00041 
00042 #include <time.h>
00043 
00044 #ifdef _WIN32
00045 #define open _open
00046 #define close _close
00047 #endif
00048 
00049 #include "MEM_guardedalloc.h"
00050 
00051 #include "DNA_constraint_types.h"
00052 #include "DNA_screen_types.h"
00053 #include "DNA_space_types.h"
00054 #include "DNA_movieclip_types.h"
00055 #include "DNA_object_types.h"
00056 #include "DNA_scene_types.h"
00057 #include "DNA_view3d_types.h"
00058 
00059 #include "BLI_utildefines.h"
00060 
00061 #include "BLI_blenlib.h"
00062 #include "BLI_ghash.h"
00063 #include "BLI_math.h"
00064 #include "BLI_mempool.h"
00065 #include "BLI_threads.h"
00066 
00067 #include "BKE_constraint.h"
00068 #include "BKE_library.h"
00069 #include "BKE_global.h"
00070 #include "BKE_main.h"
00071 #include "BKE_utildefines.h"
00072 #include "BKE_movieclip.h"
00073 #include "BKE_image.h"  /* openanim */
00074 #include "BKE_tracking.h"
00075 
00076 #include "IMB_imbuf_types.h"
00077 #include "IMB_imbuf.h"
00078 #include "IMB_moviecache.h"
00079 
00080 /*********************** movieclip buffer loaders *************************/
00081 
00082 static int sequence_guess_offset(const char *full_name, int head_len, int numlen)
00083 {
00084     char num[FILE_MAX]= {0};
00085 
00086     BLI_strncpy(num, full_name+head_len, numlen+1);
00087 
00088     return atoi(num);
00089 }
00090 
00091 static int rendersize_to_proxy(MovieClipUser *user, int flag)
00092 {
00093     if((flag&MCLIP_USE_PROXY)==0)
00094         return IMB_PROXY_NONE;
00095 
00096     switch(user->render_size) {
00097         case MCLIP_PROXY_RENDER_SIZE_25:
00098             return IMB_PROXY_25;
00099 
00100         case MCLIP_PROXY_RENDER_SIZE_50:
00101             return IMB_PROXY_50;
00102 
00103         case MCLIP_PROXY_RENDER_SIZE_75:
00104             return IMB_PROXY_75;
00105 
00106         case MCLIP_PROXY_RENDER_SIZE_100:
00107             return IMB_PROXY_100;
00108 
00109         case MCLIP_PROXY_RENDER_SIZE_FULL:
00110             return IMB_PROXY_NONE;
00111     }
00112 
00113     return IMB_PROXY_NONE;
00114 }
00115 
00116 static int rendersize_to_number(int render_size)
00117 {
00118     switch(render_size) {
00119         case MCLIP_PROXY_RENDER_SIZE_25:
00120             return 25;
00121 
00122         case MCLIP_PROXY_RENDER_SIZE_50:
00123             return 50;
00124 
00125         case MCLIP_PROXY_RENDER_SIZE_75:
00126             return 75;
00127 
00128         case MCLIP_PROXY_RENDER_SIZE_100:
00129             return 100;
00130 
00131         case MCLIP_PROXY_RENDER_SIZE_FULL:
00132             return 100;
00133     }
00134 
00135     return 100;
00136 }
00137 
00138 static int get_timecode(MovieClip *clip, int flag)
00139 {
00140     if((flag&MCLIP_USE_PROXY)==0)
00141         return IMB_TC_NONE;
00142 
00143     return clip->proxy.tc;
00144 }
00145 
00146 static void get_sequence_fname(MovieClip *clip, int framenr, char *name)
00147 {
00148     unsigned short numlen;
00149     char head[FILE_MAX], tail[FILE_MAX];
00150     int offset;
00151 
00152     BLI_strncpy(name, clip->name, sizeof(clip->name));
00153     BLI_stringdec(name, head, tail, &numlen);
00154 
00155     /* movieclips always points to first image from sequence,
00156        autoguess offset for now. could be something smarter in the future */
00157     offset= sequence_guess_offset(clip->name, strlen(head), numlen);
00158 
00159     if (numlen) BLI_stringenc(name, head, tail, numlen, offset+framenr-1);
00160     else        BLI_strncpy(name, clip->name, sizeof(clip->name));
00161 
00162     BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
00163 }
00164 
00165 /* supposed to work with sequences only */
00166 static void get_proxy_fname(MovieClip *clip, int proxy_render_size, int undistorted, int framenr, char *name)
00167 {
00168     int size= rendersize_to_number(proxy_render_size);
00169     char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
00170 
00171     BLI_split_dirfile(clip->name, clipdir, clipfile, FILE_MAX, FILE_MAX);
00172 
00173     if(clip->flag&MCLIP_USE_PROXY_CUSTOM_DIR) {
00174         BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
00175     } else {
00176         BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
00177     }
00178 
00179     if(undistorted)
00180         BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, framenr);
00181     else
00182         BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, framenr);
00183 
00184     BLI_path_abs(name, G.main->name);
00185     BLI_path_frame(name, 1, 0);
00186 
00187     strcat(name, ".jpg");
00188 }
00189 
00190 static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
00191 {
00192     struct ImBuf *ibuf;
00193     char name[FILE_MAX];
00194     int loadflag, use_proxy= 0;
00195 
00196     use_proxy= (flag&MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
00197     if(use_proxy) {
00198         int undistort= user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT;
00199         get_proxy_fname(clip, user->render_size, undistort, framenr, name);
00200     } else
00201         get_sequence_fname(clip, framenr, name);
00202 
00203     loadflag= IB_rect|IB_multilayer;
00204 
00205     /* read ibuf */
00206     ibuf= IMB_loadiffname(name, loadflag);
00207 
00208     return ibuf;
00209 }
00210 
00211 static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
00212 {
00213     ImBuf *ibuf= NULL;
00214     int tc= get_timecode(clip, flag);
00215     int proxy= rendersize_to_proxy(user, flag);
00216     char str[FILE_MAX];
00217 
00218     if(!clip->anim) {
00219         BLI_strncpy(str, clip->name, FILE_MAX);
00220         BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id));
00221 
00222         /* FIXME: make several stream accessible in image editor, too */
00223         clip->anim= openanim(str, IB_rect, 0);
00224 
00225         if(clip->anim) {
00226             if(clip->flag&MCLIP_USE_PROXY_CUSTOM_DIR) {
00227                 char dir[FILE_MAX];
00228                 BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
00229                 BLI_path_abs(dir, G.main->name);
00230                 IMB_anim_set_index_dir(clip->anim, dir);
00231             }
00232         }
00233     }
00234 
00235     if(clip->anim) {
00236         int dur;
00237         int fra;
00238 
00239         dur= IMB_anim_get_duration(clip->anim, tc);
00240         fra= framenr-1;
00241 
00242         if(fra<0)
00243             fra= 0;
00244 
00245         if(fra>(dur-1))
00246             fra= dur-1;
00247 
00248         ibuf= IMB_anim_absolute(clip->anim, fra, tc, proxy);
00249     }
00250 
00251     return ibuf;
00252 }
00253 
00254 /*********************** image buffer cache *************************/
00255 
00256 typedef struct MovieClipCache {
00257     /* regular movie cache */
00258     struct MovieCache *moviecache;
00259 
00260     /* cached postprocessed shot */
00261     struct {
00262         ImBuf *ibuf;
00263         int framenr;
00264         int flag;
00265 
00266         /* cache for undistorted shot */
00267         float principal[2];
00268         float k1, k2, k3;
00269         short undistoriton_used;
00270 
00271         int proxy;
00272         short render_flag;
00273     } postprocessed;
00274 
00275     /* cache for stable shot */
00276     struct {
00277         ImBuf *ibuf;
00278         int framenr;
00279 
00280         float loc[2], scale, angle;
00281         int proxy;
00282         short render_flag;
00283     } stabilized;
00284 } MovieClipCache;
00285 
00286 typedef struct MovieClipImBufCacheKey {
00287     int framenr;
00288     int proxy;
00289     short render_flag;
00290 } MovieClipImBufCacheKey;
00291 
00292 static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
00293 {
00294     MovieClipImBufCacheKey *key= (MovieClipImBufCacheKey*)userkey;
00295 
00296     *framenr= key->framenr;
00297     *proxy= key->proxy;
00298     *render_flags= key->render_flag;
00299 }
00300 
00301 static unsigned int moviecache_hashhash(const void *keyv)
00302 {
00303     MovieClipImBufCacheKey *key= (MovieClipImBufCacheKey*)keyv;
00304     int rval= key->framenr;
00305 
00306     return rval;
00307 }
00308 
00309 static int moviecache_hashcmp(const void *av, const void *bv)
00310 {
00311     const MovieClipImBufCacheKey *a= (MovieClipImBufCacheKey*)av;
00312     const MovieClipImBufCacheKey *b= (MovieClipImBufCacheKey*)bv;
00313 
00314     if(a->framenr<b->framenr) return -1;
00315     else if(a->framenr>b->framenr) return 1;
00316 
00317     if(a->proxy<b->proxy) return -1;
00318     else if(a->proxy>b->proxy) return 1;
00319 
00320     if(a->render_flag<b->render_flag) return -1;
00321     else if(a->render_flag>b->render_flag) return 1;
00322 
00323     return 0;
00324 }
00325 
00326 static ImBuf *get_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
00327 {
00328     if(clip->cache) {
00329         MovieClipImBufCacheKey key;
00330 
00331         key.framenr= user->framenr;
00332 
00333         if(flag&MCLIP_USE_PROXY) {
00334             key.proxy= rendersize_to_proxy(user, flag);
00335             key.render_flag= user->render_flag;
00336         }
00337         else {
00338             key.proxy= IMB_PROXY_NONE;
00339             key.render_flag= 0;
00340         }
00341 
00342         return IMB_moviecache_get(clip->cache->moviecache, &key);
00343     }
00344 
00345     return NULL;
00346 }
00347 
00348 static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag)
00349 {
00350     MovieClipImBufCacheKey key;
00351 
00352     if(!clip->cache) {
00353         clip->cache= MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
00354 
00355         clip->cache->moviecache= IMB_moviecache_create(sizeof(MovieClipImBufCacheKey), moviecache_hashhash,
00356                 moviecache_hashcmp, moviecache_keydata);
00357     }
00358 
00359     key.framenr= user->framenr;
00360 
00361     if(flag&MCLIP_USE_PROXY) {
00362         key.proxy= rendersize_to_proxy(user, flag);
00363         key.render_flag= user->render_flag;
00364     }
00365     else {
00366         key.proxy= IMB_PROXY_NONE;
00367         key.render_flag= 0;
00368     }
00369 
00370     IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
00371 }
00372 
00373 /*********************** common functions *************************/
00374 
00375 /* only image block itself */
00376 static MovieClip *movieclip_alloc(const char *name)
00377 {
00378     MovieClip *clip;
00379 
00380     clip= alloc_libblock(&G.main->movieclip, ID_MC, name);
00381 
00382     clip->aspx= clip->aspy= 1.0f;
00383 
00384     BKE_tracking_init_settings(&clip->tracking);
00385 
00386     clip->proxy.build_size_flag= IMB_PROXY_25;
00387     clip->proxy.build_tc_flag= IMB_TC_RECORD_RUN |
00388                                IMB_TC_FREE_RUN |
00389                                IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN |
00390                                IMB_TC_RECORD_RUN_NO_GAPS;
00391     clip->proxy.quality= 90;
00392 
00393     return clip;
00394 }
00395 
00396 /* checks if image was already loaded, then returns same image
00397    otherwise creates new.
00398    does not load ibuf itself
00399    pass on optional frame for #name images */
00400 MovieClip *BKE_add_movieclip_file(const char *name)
00401 {
00402     MovieClip *clip;
00403     MovieClipUser user;
00404     int file, len, width, height;
00405     const char *libname;
00406     char str[FILE_MAX], strtest[FILE_MAX];
00407 
00408     BLI_strncpy(str, name, sizeof(str));
00409     BLI_path_abs(str, G.main->name);
00410 
00411     /* exists? */
00412     file= open(str, O_BINARY|O_RDONLY);
00413     if(file== -1) return NULL;
00414     close(file);
00415 
00416     /* ** first search an identical clip ** */
00417     for(clip= G.main->movieclip.first; clip; clip= clip->id.next) {
00418         BLI_strncpy(strtest, clip->name, sizeof(clip->name));
00419         BLI_path_abs(strtest, G.main->name);
00420 
00421         if(strcmp(strtest, str)==0) {
00422             BLI_strncpy(clip->name, name, sizeof(clip->name));  /* for stringcode */
00423             clip->id.us++;  /* officially should not, it doesn't link here! */
00424 
00425             return clip;
00426         }
00427     }
00428 
00429     /* ** add new movieclip ** */
00430 
00431     /* create a short library name */
00432     len= strlen(name);
00433 
00434     while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--;
00435     libname= name+len;
00436 
00437     clip= movieclip_alloc(libname);
00438     BLI_strncpy(clip->name, name, sizeof(clip->name));
00439 
00440     if(BLI_testextensie_array(name, imb_ext_movie)) clip->source= MCLIP_SRC_MOVIE;
00441     else clip->source= MCLIP_SRC_SEQUENCE;
00442 
00443     user.framenr= 1;
00444     BKE_movieclip_get_size(clip, &user, &width, &height);
00445     if(width && height) {
00446         clip->tracking.camera.principal[0]= ((float)width)/2;
00447         clip->tracking.camera.principal[1]= ((float)height)/2;
00448 
00449         clip->tracking.camera.focal= 24.0f*width/clip->tracking.camera.sensor_width;
00450     }
00451 
00452     return clip;
00453 }
00454 
00455 static void real_ibuf_size(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int *width, int *height)
00456 {
00457     *width= ibuf->x;
00458     *height= ibuf->y;
00459 
00460     if(clip->flag&MCLIP_USE_PROXY) {
00461         switch(user->render_size) {
00462             case MCLIP_PROXY_RENDER_SIZE_25:
00463                 (*width)*= 4;
00464                 (*height)*= 4;
00465                 break;
00466 
00467             case MCLIP_PROXY_RENDER_SIZE_50:
00468                 (*width)*= 2.0f;
00469                 (*height)*= 2.0f;
00470                 break;
00471 
00472             case MCLIP_PROXY_RENDER_SIZE_75:
00473                 *width= ((float)*width)*4.0f/3.0f;
00474                 *height= ((float)*height)*4.0f/3.0f;
00475                 break;
00476         }
00477     }
00478 }
00479 
00480 static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *distortion, ImBuf *ibuf)
00481 {
00482     ImBuf *undistibuf;
00483 
00484     /* XXX: because of #27997 do not use float buffers to undistort,
00485             otherwise, undistorted proxy can be darker than it should */
00486     imb_freerectfloatImBuf(ibuf);
00487 
00488     if(distortion)
00489         undistibuf= BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1);
00490     else
00491         undistibuf= BKE_tracking_undistort(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
00492 
00493     if(undistibuf->userflags&IB_RECT_INVALID) {
00494         ibuf->userflags&= ~IB_RECT_INVALID;
00495         IMB_rect_from_float(undistibuf);
00496     }
00497 
00498     IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y);
00499 
00500     return undistibuf;
00501 }
00502 
00503 static int need_undistortion_postprocess(MovieClipUser *user, int flag)
00504 {
00505     int result = 0;
00506 
00507     /* only full undistorted render can be used as on-fly undistorting image */
00508     if(flag & MCLIP_USE_PROXY) {
00509         result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) &&
00510                   (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
00511     }
00512 
00513     return result;
00514 }
00515 
00516 static int need_postprocessed_frame(MovieClipUser *user, int flag, int postprocess_flag)
00517 {
00518     int result = postprocess_flag;
00519 
00520     result |= need_undistortion_postprocess(user, flag);
00521 
00522     return result;
00523 }
00524 
00525 static int check_undistortion_cache_flags(MovieClip *clip)
00526 {
00527     MovieClipCache *cache= clip->cache;
00528     MovieTrackingCamera *camera= &clip->tracking.camera;
00529 
00530     /* check for distortion model changes */
00531     if(!equals_v2v2(camera->principal, cache->postprocessed.principal))
00532         return 0;
00533 
00534     if(!equals_v3v3(&camera->k1, &cache->postprocessed.k1))
00535         return 0;
00536 
00537     return 1;
00538 }
00539 
00540 static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *user, int flag, int postprocess_flag)
00541 {
00542     MovieClipCache *cache= clip->cache;
00543     int framenr= user->framenr;
00544     short proxy= IMB_PROXY_NONE;
00545     int render_flag= 0;
00546 
00547     if(flag&MCLIP_USE_PROXY) {
00548         proxy= rendersize_to_proxy(user, flag);
00549         render_flag= user->render_flag;
00550     }
00551 
00552     /* no cache or no cached postprocessed image */
00553     if(!clip->cache || !clip->cache->postprocessed.ibuf)
00554         return NULL;
00555 
00556     /* postprocessing happened for other frame */
00557     if(cache->postprocessed.framenr != framenr)
00558         return NULL;
00559 
00560     /* cached ibuf used different proxy settings */
00561     if(cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy)
00562         return NULL;
00563 
00564     if(cache->postprocessed.flag != postprocess_flag)
00565         return NULL;
00566 
00567     if(need_undistortion_postprocess(user, flag)) {
00568         if(!check_undistortion_cache_flags(clip))
00569             return NULL;
00570     }
00571     else if(cache->postprocessed.undistoriton_used)
00572         return NULL;
00573 
00574     IMB_refImBuf(cache->postprocessed.ibuf);
00575 
00576     return cache->postprocessed.ibuf;
00577 }
00578 
00579 static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
00580 {
00581     MovieClipCache *cache= clip->cache;
00582     MovieTrackingCamera *camera= &clip->tracking.camera;
00583     ImBuf *postproc_ibuf = NULL;
00584 
00585     if(cache->postprocessed.ibuf)
00586         IMB_freeImBuf(cache->postprocessed.ibuf);
00587 
00588     cache->postprocessed.framenr= user->framenr;
00589     cache->postprocessed.flag = postprocess_flag;
00590 
00591     if(flag&MCLIP_USE_PROXY) {
00592         cache->postprocessed.proxy= rendersize_to_proxy(user, flag);
00593         cache->postprocessed.render_flag= user->render_flag;
00594     }
00595     else {
00596         cache->postprocessed.proxy = IMB_PROXY_NONE;
00597         cache->postprocessed.render_flag = 0;
00598     }
00599 
00600     if(need_undistortion_postprocess(user, flag)) {
00601         copy_v2_v2(cache->postprocessed.principal, camera->principal);
00602         copy_v3_v3(&cache->postprocessed.k1, &camera->k1);
00603         cache->postprocessed.undistoriton_used = 1;
00604         postproc_ibuf= get_undistorted_ibuf(clip, NULL, ibuf);
00605     }
00606     else cache->postprocessed.undistoriton_used = 0;
00607 
00608     if(postprocess_flag) {
00609         int disable_red   = postprocess_flag & MOVIECLIP_DISABLE_RED,
00610             disable_green = postprocess_flag & MOVIECLIP_DISABLE_GREEN,
00611             disable_blue  = postprocess_flag & MOVIECLIP_DISABLE_BLUE,
00612             grayscale     = postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE;
00613 
00614         if(!postproc_ibuf)
00615             postproc_ibuf = IMB_dupImBuf(ibuf);
00616 
00617         if(disable_red || disable_green || disable_blue || grayscale)
00618             BKE_tracking_disable_imbuf_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
00619     }
00620 
00621     IMB_refImBuf(postproc_ibuf);
00622 
00623     cache->postprocessed.ibuf= postproc_ibuf;
00624 
00625     if(cache->stabilized.ibuf) {
00626         /* force stable buffer be re-calculated */
00627         IMB_freeImBuf(cache->stabilized.ibuf);
00628         cache->stabilized.ibuf= NULL;
00629     }
00630 
00631     return postproc_ibuf;
00632 }
00633 
00634 static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int flag, int postprocess_flag)
00635 {
00636     ImBuf *ibuf= NULL;
00637     int framenr= user->framenr, need_postprocess= 0;
00638 
00639     /* cache isn't threadsafe itself and also loading of movies
00640        can't happen from concurent threads that's why we use lock here */
00641     BLI_lock_thread(LOCK_MOVIECLIP);
00642 
00643     /* try to obtain cached postprocessed frame first */
00644     if(need_postprocessed_frame(user, flag, postprocess_flag)) {
00645         ibuf= get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
00646 
00647         if(!ibuf)
00648             need_postprocess= 1;
00649     }
00650 
00651     if(!ibuf)
00652         ibuf= get_imbuf_cache(clip, user, flag);
00653 
00654     if(!ibuf) {
00655         int use_sequence= 0;
00656 
00657         /* undistorted proxies for movies should be read as image sequence */
00658         use_sequence= (user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT) &&
00659             (user->render_size!=MCLIP_PROXY_RENDER_SIZE_FULL);
00660 
00661         if(clip->source==MCLIP_SRC_SEQUENCE || use_sequence)
00662             ibuf= movieclip_load_sequence_file(clip, user, framenr, flag);
00663         else {
00664             ibuf= movieclip_load_movie_file(clip, user, framenr, flag);
00665         }
00666 
00667         if(ibuf)
00668             put_imbuf_cache(clip, user, ibuf, flag);
00669     }
00670 
00671     if(ibuf) {
00672         clip->lastframe= framenr;
00673         real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
00674 
00675         /* postprocess frame and put to cache */
00676         if(need_postprocess) {
00677             ImBuf *tmpibuf= ibuf;
00678             ibuf= put_postprocessed_frame_to_cache(clip, user, tmpibuf, flag, postprocess_flag);
00679             IMB_freeImBuf(tmpibuf);
00680         }
00681     }
00682 
00683     BLI_unlock_thread(LOCK_MOVIECLIP);
00684 
00685     return ibuf;
00686 }
00687 
00688 ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user)
00689 {
00690     return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag);
00691 }
00692 
00693 ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag)
00694 {
00695     return movieclip_get_postprocessed_ibuf(clip, user, flag, 0);
00696 }
00697 
00698 ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int postprocess_flag)
00699 {
00700     return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag);
00701 }
00702 
00703 static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, int framenr)
00704 {
00705     MovieClipCache *cache = clip->cache;
00706     ImBuf *stableibuf;
00707     float tloc[2], tscale, tangle;
00708     short proxy = IMB_PROXY_NONE;
00709     int render_flag = 0;
00710 
00711     if(clip->flag&MCLIP_USE_PROXY) {
00712         proxy = rendersize_to_proxy(user, clip->flag);
00713         render_flag = user->render_flag;
00714     }
00715 
00716     /* there's no cached frame or it was calculated for another frame */
00717     if(!cache->stabilized.ibuf || cache->stabilized.framenr != framenr)
00718         return NULL;
00719 
00720     /* cached ibuf used different proxy settings */
00721     if(cache->stabilized.render_flag!=render_flag || cache->stabilized.proxy!=proxy)
00722         return NULL;
00723 
00724     stableibuf = cache->stabilized.ibuf;
00725 
00726     BKE_tracking_stabilization_data(&clip->tracking, framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
00727 
00728     /* check for stabilization parameters */
00729     if(tscale != cache->stabilized.scale ||
00730        tangle != cache->stabilized.angle ||
00731        !equals_v2v2(tloc, cache->stabilized.loc))
00732     {
00733         return NULL;
00734     }
00735 
00736     IMB_refImBuf(stableibuf);
00737 
00738     return stableibuf;
00739 }
00740 
00741 static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int framenr)
00742 {
00743     MovieClipCache *cache = clip->cache;
00744     ImBuf *stableibuf;
00745     float tloc[2], tscale, tangle;
00746 
00747     if(cache->stabilized.ibuf)
00748         IMB_freeImBuf(cache->stabilized.ibuf);
00749 
00750     stableibuf = BKE_tracking_stabilize(&clip->tracking, framenr, ibuf, tloc, &tscale, &tangle);
00751 
00752     cache->stabilized.ibuf= stableibuf;
00753 
00754     copy_v2_v2(cache->stabilized.loc, tloc);
00755 
00756     cache->stabilized.scale = tscale;
00757     cache->stabilized.angle = tangle;
00758     cache->stabilized.framenr = framenr;
00759 
00760     if(clip->flag&MCLIP_USE_PROXY) {
00761         cache->stabilized.proxy= rendersize_to_proxy(user, clip->flag);
00762         cache->stabilized.render_flag= user->render_flag;
00763     }
00764     else {
00765         cache->stabilized.proxy = IMB_PROXY_NONE;
00766         cache->stabilized.render_flag = 0;
00767     }
00768 
00769     IMB_refImBuf(stableibuf);
00770 
00771     return stableibuf;
00772 }
00773 
00774 ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle, int postprocess_flag)
00775 {
00776     ImBuf *ibuf, *stableibuf= NULL;
00777     int framenr= user->framenr;
00778 
00779     ibuf= BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
00780 
00781     if(!ibuf)
00782         return NULL;
00783 
00784     if(clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) {
00785         MovieClipCache *cache= clip->cache;
00786 
00787         stableibuf= get_stable_cached_frame(clip, user, framenr);
00788 
00789         if(!stableibuf)
00790             stableibuf= put_stabilized_frame_to_cache(clip, user, ibuf, framenr);
00791 
00792         if(loc)     copy_v2_v2(loc, cache->stabilized.loc);
00793         if(scale)   *scale= cache->stabilized.scale;
00794         if(angle)   *angle= cache->stabilized.angle;
00795     } else {
00796         if(loc)     zero_v2(loc);
00797         if(scale)   *scale= 1.0f;
00798         if(angle)   *angle= 0.0f;
00799 
00800         stableibuf= ibuf;
00801     }
00802 
00803     if(stableibuf!=ibuf) {
00804         IMB_freeImBuf(ibuf);
00805         ibuf= stableibuf;
00806     }
00807 
00808     return ibuf;
00809 
00810 }
00811 
00812 int BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
00813 {
00814     ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
00815 
00816     if(ibuf) {
00817         IMB_freeImBuf(ibuf);
00818         return 1;
00819     }
00820 
00821     return 0;
00822 }
00823 
00824 void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
00825 {
00826     if(user->framenr==clip->lastframe) {
00827         *width= clip->lastsize[0];
00828         *height= clip->lastsize[1];
00829     } else {
00830         ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
00831 
00832         if(ibuf && ibuf->x && ibuf->y) {
00833             real_ibuf_size(clip, user, ibuf, width, height);
00834         } else {
00835             *width= 0;
00836             *height= 0;
00837         }
00838 
00839         if(ibuf)
00840             IMB_freeImBuf(ibuf);
00841     }
00842 }
00843 
00844 void BKE_movieclip_aspect(MovieClip *clip, float *aspx, float *aspy)
00845 {
00846     *aspx= *aspy= 1.0;
00847 
00848     /* x is always 1 */
00849     *aspy = clip->aspy/clip->aspx/clip->tracking.camera.pixel_aspect;
00850 }
00851 
00852 /* get segments of cached frames. useful for debugging cache policies */
00853 void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *totseg_r, int **points_r)
00854 {
00855     *totseg_r= 0;
00856     *points_r= NULL;
00857 
00858     if(clip->cache) {
00859         int proxy= rendersize_to_proxy(user, clip->flag);
00860 
00861         IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, totseg_r, points_r);
00862     }
00863 }
00864 
00865 void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
00866 {
00867     /* TODO: clamp framenr here? */
00868 
00869     iuser->framenr= framenr;
00870 }
00871 
00872 static void free_buffers(MovieClip *clip)
00873 {
00874     if(clip->cache) {
00875         IMB_moviecache_free(clip->cache->moviecache);
00876 
00877         if(clip->cache->postprocessed.ibuf)
00878             IMB_freeImBuf(clip->cache->postprocessed.ibuf);
00879 
00880         if(clip->cache->stabilized.ibuf)
00881             IMB_freeImBuf(clip->cache->stabilized.ibuf);
00882 
00883         MEM_freeN(clip->cache);
00884         clip->cache= NULL;
00885     }
00886 
00887     if(clip->anim) {
00888         IMB_free_anim(clip->anim);
00889         clip->anim= FALSE;
00890     }
00891 }
00892 
00893 void BKE_movieclip_reload(MovieClip *clip)
00894 {
00895     /* clear cache */
00896     free_buffers(clip);
00897 
00898     clip->tracking.stabilization.ok= 0;
00899 
00900     /* update clip source */
00901     if(BLI_testextensie_array(clip->name, imb_ext_movie)) clip->source= MCLIP_SRC_MOVIE;
00902     else clip->source= MCLIP_SRC_SEQUENCE;
00903 }
00904 
00905 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
00906 {
00907     if(scopes->ok)
00908         return;
00909 
00910     if(scopes->track_preview) {
00911         IMB_freeImBuf(scopes->track_preview);
00912         scopes->track_preview= NULL;
00913     }
00914 
00915     scopes->marker= NULL;
00916     scopes->track= NULL;
00917 
00918     if(clip) {
00919         MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking);
00920 
00921         if(act_track) {
00922             MovieTrackingTrack *track= act_track;
00923             MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
00924 
00925             if(marker->flag&MARKER_DISABLED) {
00926                 scopes->track_disabled= 1;
00927             } else {
00928                 ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
00929 
00930                 scopes->track_disabled= 0;
00931 
00932                 if(ibuf && ibuf->rect) {
00933                     ImBuf *tmpibuf;
00934                     MovieTrackingMarker undist_marker= *marker;
00935 
00936                     if(user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT) {
00937                         int width, height;
00938                         float aspy= 1.0f/clip->tracking.camera.pixel_aspect;;
00939 
00940                         BKE_movieclip_get_size(clip, user, &width, &height);
00941 
00942                         undist_marker.pos[0]*= width;
00943                         undist_marker.pos[1]*= height*aspy;
00944 
00945                         BKE_tracking_invert_intrinsics(&clip->tracking, undist_marker.pos, undist_marker.pos);
00946 
00947                         undist_marker.pos[0]/= width;
00948                         undist_marker.pos[1]/= height*aspy;
00949                     }
00950 
00951                     /* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */
00952                     tmpibuf= BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */,
00953                             1 /* anchor */, scopes->track_pos, NULL);
00954 
00955                     if(tmpibuf->rect_float)
00956                         IMB_rect_from_float(tmpibuf);
00957 
00958                     if(tmpibuf->rect)
00959                         scopes->track_preview= tmpibuf;
00960                     else
00961                         IMB_freeImBuf(tmpibuf);
00962                 }
00963 
00964                 IMB_freeImBuf(ibuf);
00965             }
00966 
00967             if((track->flag&TRACK_LOCKED)==0) {
00968                 scopes->marker= marker;
00969                 scopes->track= track;
00970                 scopes->slide_scale[0]= track->pat_max[0]-track->pat_min[0];
00971                 scopes->slide_scale[1]= track->pat_max[1]-track->pat_min[1];
00972             }
00973         }
00974     }
00975 
00976     scopes->framenr= user->framenr;
00977     scopes->ok= 1;
00978 }
00979 
00980 static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted)
00981 {
00982     char name[FILE_MAX];
00983     int quality, rectx, recty;
00984     int size= size= rendersize_to_number(proxy_render_size);
00985     ImBuf *scaleibuf;
00986 
00987     get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
00988 
00989     rectx= ibuf->x*size/100.0f;
00990     recty= ibuf->y*size/100.0f;
00991 
00992     scaleibuf= IMB_dupImBuf(ibuf);
00993 
00994     IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
00995 
00996     quality= clip->proxy.quality;
00997     scaleibuf->ftype= JPG | quality;
00998 
00999     /* unsupported feature only confuses other s/w */
01000     if(scaleibuf->planes==32)
01001         scaleibuf->planes= 24;
01002 
01003     BLI_lock_thread(LOCK_MOVIECLIP);
01004 
01005     BLI_make_existing_file(name);
01006     if(IMB_saveiff(scaleibuf, name, IB_rect)==0)
01007         perror(name);
01008 
01009     BLI_unlock_thread(LOCK_MOVIECLIP);
01010 
01011     IMB_freeImBuf(scaleibuf);
01012 }
01013 
01014 void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
01015             int cfra, int *build_sizes, int build_count, int undistorted)
01016 {
01017     ImBuf *ibuf;
01018     MovieClipUser user;
01019 
01020     user.framenr= cfra;
01021     user.render_flag= 0;
01022     user.render_size= MCLIP_PROXY_RENDER_SIZE_FULL;
01023 
01024     ibuf= BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag);
01025 
01026     if(ibuf) {
01027         ImBuf *tmpibuf= ibuf;
01028         int i;
01029 
01030         if(undistorted)
01031             tmpibuf= get_undistorted_ibuf(clip, distortion, ibuf);
01032 
01033         for(i= 0; i<build_count; i++)
01034             movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted);
01035 
01036         IMB_freeImBuf(ibuf);
01037 
01038         if(tmpibuf!=ibuf)
01039             IMB_freeImBuf(tmpibuf);
01040     }
01041 }
01042 
01043 void free_movieclip(MovieClip *clip)
01044 {
01045     free_buffers(clip);
01046 
01047     BKE_tracking_free(&clip->tracking);
01048 }
01049 
01050 void unlink_movieclip(Main *bmain, MovieClip *clip)
01051 {
01052     bScreen *scr;
01053     ScrArea *area;
01054     SpaceLink *sl;
01055     Scene *sce;
01056     Object *ob;
01057 
01058     for(scr= bmain->screen.first; scr; scr= scr->id.next) {
01059         for(area= scr->areabase.first; area; area= area->next) {
01060             for(sl= area->spacedata.first; sl; sl= sl->next) {
01061                 if(sl->spacetype==SPACE_CLIP) {
01062                     SpaceClip *sc= (SpaceClip *) sl;
01063 
01064                     if(sc->clip==clip)
01065                         sc->clip= NULL;
01066                 }
01067                 else if(sl->spacetype==SPACE_VIEW3D) {
01068                     View3D *v3d= (View3D *) sl;
01069                     BGpic *bgpic;
01070 
01071                     for(bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
01072                         if(bgpic->clip==clip)
01073                             bgpic->clip= NULL;
01074                     }
01075                 }
01076             }
01077         }
01078     }
01079 
01080     for(sce= bmain->scene.first; sce; sce= sce->id.next) {
01081         if(sce->clip==clip)
01082             sce->clip= NULL;
01083     }
01084 
01085     for(ob= bmain->object.first; ob; ob= ob->id.next) {
01086         bConstraint *con;
01087 
01088         for(con= ob->constraints.first; con; con= con->next) {
01089             bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
01090 
01091             if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) {
01092                 bFollowTrackConstraint *data= (bFollowTrackConstraint *) con->data;
01093 
01094                 if(data->clip==clip)
01095                     data->clip= NULL;
01096             }
01097             else if(cti->type==CONSTRAINT_TYPE_CAMERASOLVER) {
01098                 bCameraSolverConstraint *data= (bCameraSolverConstraint *) con->data;
01099 
01100                 if(data->clip==clip)
01101                     data->clip= NULL;
01102             }
01103         }
01104     }
01105 
01106     clip->id.us= 0;
01107 }