Blender V2.61 - r43446
|
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 }