diff options
Diffstat (limited to 'source/blender/editors/space_clip/clip_ops.c')
-rw-r--r-- | source/blender/editors/space_clip/clip_ops.c | 288 |
1 files changed, 241 insertions, 47 deletions
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 4e53f34359e..8e03691e64f 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -30,16 +30,26 @@ */ #include <errno.h> +#include <sys/types.h> +#include <fcntl.h> + +#ifndef WIN32 +# include <unistd.h> +#else +# include <io.h> +#endif #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" #include "DNA_scene_types.h" /* min/max frames */ -#include "BLI_path_util.h" #include "BLI_utildefines.h" +#include "BLI_fileops.h" +#include "BLI_path_util.h" #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_threads.h" #include "BLF_translation.h" @@ -113,7 +123,7 @@ static void sclip_zoom_set_factor(const bContext *C, float zoomfac, float locati sclip_zoom_set(C, sc->zoom * zoomfac, location); } -static void sclip_zoom_set_factor_exec(bContext *C, wmEvent *event, float factor) +static void sclip_zoom_set_factor_exec(bContext *C, const wmEvent *event, float factor) { ARegion *ar = CTX_wm_region(C); @@ -160,6 +170,7 @@ static int open_exec(bContext *C, wmOperator *op) { SpaceClip *sc = CTX_wm_space_clip(C); bScreen *screen = CTX_wm_screen(C); + Main *bmain = CTX_data_main(C); PropertyPointerRNA *pprop; PointerRNA idptr; MovieClip *clip = NULL; @@ -191,7 +202,7 @@ static int open_exec(bContext *C, wmOperator *op) errno = 0; - clip = BKE_movieclip_file_add(str); + clip = BKE_movieclip_file_add(bmain, str); if (!clip) { if (op->customdata) @@ -229,7 +240,7 @@ static int open_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceClip *sc = CTX_wm_space_clip(C); char path[FILE_MAX]; @@ -317,7 +328,7 @@ typedef struct ViewPanData { float *vec; } ViewPanData; -static void view_pan_init(bContext *C, wmOperator *op, wmEvent *event) +static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ViewPanData *vpd; @@ -376,14 +387,14 @@ static int view_pan_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type == MOUSEPAN) { SpaceClip *sc = CTX_wm_space_clip(C); float offset[2]; - offset[0] = (event->x - event->prevx) / sc->zoom; - offset[1] = (event->y - event->prevy) / sc->zoom; + offset[0] = (event->prevx - event->x) / sc->zoom; + offset[1] = (event->prevy - event->y) / sc->zoom; RNA_float_set_array(op->ptr, "offset", offset); @@ -398,7 +409,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) } } -static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) +static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ViewPanData *vpd = op->customdata; @@ -470,7 +481,7 @@ typedef struct ViewZoomData { float location[2]; } ViewZoomData; -static void view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) +static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -513,12 +524,12 @@ static int view_zoom_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (event->type == MOUSEZOOM) { + if (event->type == MOUSEZOOM || event->type == MOUSEPAN) { float delta, factor; - delta = event->x - event->prevx + event->y - event->prevy; + delta = event->prevx - event->x + event->prevy - event->y; if (U.uiflag & USER_ZOOM_INVERT) delta *= -1; @@ -537,7 +548,7 @@ static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) } } -static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event) { ViewZoomData *vpd = op->customdata; float delta, factor; @@ -610,7 +621,7 @@ static int view_zoom_in_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_zoom_in_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -653,7 +664,7 @@ static int view_zoom_out_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_zoom_out_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -843,7 +854,7 @@ static int change_frame_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int frame_from_event(bContext *C, wmEvent *event) +static int frame_from_event(bContext *C, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); @@ -865,7 +876,7 @@ static int frame_from_event(bContext *C, wmEvent *event) return framenr; } -static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); @@ -884,7 +895,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event) +static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case ESCKEY: @@ -908,7 +919,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event) void CLIP_OT_change_frame(wmOperatorType *ot) { /* identifiers */ - ot->name = "Change frame"; + ot->name = "Change Frame"; ot->idname = "CLIP_OT_change_frame"; ot->description = "Interactively change the current frame number"; @@ -970,46 +981,39 @@ static int proxy_bitflag_to_array(int size_flag, int build_sizes[4], int undisto return build_count; } -/* only this runs inside thread */ -static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress) +/* simple case for movies -- handle frame-by-frame, do threading within single frame */ +static void do_movie_proxy(void *pjv, int *UNUSED(build_sizes), int UNUSED(build_count), + int *build_undistort_sizes, int build_undistort_count, + short *stop, short *do_update, float *progress) { ProxyJob *pj = pjv; Scene *scene = pj->scene; MovieClip *clip = pj->clip; struct MovieDistortion *distortion = NULL; - short size_flag; int cfra, sfra = SFRA, efra = EFRA; - int build_sizes[4], build_count = 0; - int build_undistort_sizes[4], build_undistort_count = 0; - size_flag = clip->proxy.build_size_flag; - - build_count = proxy_bitflag_to_array(size_flag, build_sizes, 0); - build_undistort_count = proxy_bitflag_to_array(size_flag, build_undistort_sizes, 1); - - if (clip->source == MCLIP_SRC_MOVIE) { - if (pj->index_context) - IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress); + if (pj->index_context) + IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress); - if (!build_undistort_count) { - if (*stop) - pj->stop = 1; + if (!build_undistort_count) { + if (*stop) + pj->stop = 1; - return; - } - else { - sfra = 1; - efra = IMB_anim_get_duration(clip->anim, IMB_TC_NONE); - } + return; } + else { + sfra = 1; + efra = IMB_anim_get_duration(clip->anim, IMB_TC_NONE); + } + + if (build_undistort_count) { + int threads = BLI_system_thread_count(); - if (build_undistort_count) distortion = BKE_tracking_distortion_new(); + BKE_tracking_distortion_set_threads(distortion, threads); + } for (cfra = sfra; cfra <= efra; cfra++) { - if (clip->source != MCLIP_SRC_MOVIE) - BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, NULL, cfra, build_sizes, build_count, 0); - BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, distortion, cfra, build_undistort_sizes, build_undistort_count, 1); @@ -1027,6 +1031,196 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog pj->stop = 1; } +/* ***** + * special case for sequences -- handle different frames in different threads, + * loading from disk happens in critical section, decoding frame happens from + * thread for maximal speed + */ + +typedef struct ProxyQueue { + int cfra; + int sfra; + int efra; + SpinLock spin; + + short *stop; + short *do_update; + float *progress; +} ProxyQueue; + +typedef struct ProxyThread { + MovieClip *clip; + ProxyQueue *queue; + + struct MovieDistortion *distortion; + + int *build_sizes, build_count; + int *build_undistort_sizes, build_undistort_count; +} ProxyThread; + +static unsigned char *proxy_thread_next_frame(ProxyQueue *queue, MovieClip *clip, size_t *size_r, int *cfra_r) +{ + unsigned char *mem = NULL; + + BLI_spin_lock(&queue->spin); + if (!*queue->stop && queue->cfra <= queue->efra) { + MovieClipUser user = {0}; + char name[FILE_MAX]; + size_t size; + int file; + + user.framenr = queue->cfra; + + BKE_movieclip_filename_for_frame(clip, &user, name); + + file = open(name, O_BINARY | O_RDONLY, 0); + if (file < 0) { + BLI_spin_unlock(&queue->spin); + return NULL; + } + + size = BLI_file_descriptor_size(file); + if (size < 1) { + close(file); + BLI_spin_unlock(&queue->spin); + return NULL; + } + + mem = MEM_mallocN(size, "movieclip proxy memory file"); + + if (read(file, mem, size) != size) { + close(file); + BLI_spin_unlock(&queue->spin); + MEM_freeN(mem); + return NULL; + } + + *size_r = size; + *cfra_r = queue->cfra; + + queue->cfra++; + close(file); + + *queue->do_update = 1; + *queue->progress = (float)(queue->cfra - queue->sfra) / (queue->efra - queue->sfra); + } + BLI_spin_unlock(&queue->spin); + + return mem; +} + +static void *do_proxy_thread(void *data_v) +{ + ProxyThread *data = (ProxyThread *) data_v; + unsigned char *mem; + size_t size; + int cfra; + + while ((mem = proxy_thread_next_frame(data->queue, data->clip, &size, &cfra))) { + ImBuf *ibuf; + + ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, NULL, "proxy frame"); + + BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra, + data->build_sizes, data->build_count, FALSE); + + BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, data->distortion, cfra, + data->build_undistort_sizes, data->build_undistort_count, TRUE); + + IMB_freeImBuf(ibuf); + + MEM_freeN(mem); + } + + return NULL; +} + +static void do_sequence_proxy(void *pjv, int *build_sizes, int build_count, + int *build_undistort_sizes, int build_undistort_count, + short *stop, short *do_update, float *progress) +{ + ProxyJob *pj = pjv; + MovieClip *clip = pj->clip; + Scene *scene = pj->scene; + int sfra = SFRA, efra = EFRA; + ProxyThread *handles; + ListBase threads; + int i, tot_thread = BLI_system_thread_count(); + ProxyQueue queue; + + BLI_spin_init(&queue.spin); + + queue.cfra = sfra; + queue.sfra = sfra; + queue.efra = efra; + queue.stop = stop; + queue.do_update = do_update; + queue.progress = progress; + + handles = MEM_callocN(sizeof(ProxyThread) * tot_thread, "proxy threaded handles"); + + if (tot_thread > 1) + BLI_init_threads(&threads, do_proxy_thread, tot_thread); + + for (i = 0; i < tot_thread; i++) { + ProxyThread *handle = &handles[i]; + + handle->clip = clip; + handle->queue = &queue; + + handle->build_count = build_count; + handle->build_sizes = build_sizes; + + handle->build_undistort_count = build_undistort_count; + handle->build_undistort_sizes = build_undistort_sizes; + + if (build_undistort_count) + handle->distortion = BKE_tracking_distortion_new(); + + if (tot_thread > 1) + BLI_insert_thread(&threads, handle); + } + + if (tot_thread > 1) + BLI_end_threads(&threads); + else + do_proxy_thread(handles); + + MEM_freeN(handles); + + if (build_undistort_count) { + for (i = 0; i < tot_thread; i++) { + ProxyThread *handle = &handles[i]; + + BKE_tracking_distortion_free(handle->distortion); + } + } +} + +static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress) +{ + ProxyJob *pj = pjv; + MovieClip *clip = pj->clip; + + short size_flag; + int build_sizes[4], build_count = 0; + int build_undistort_sizes[4], build_undistort_count = 0; + + size_flag = clip->proxy.build_size_flag; + + build_count = proxy_bitflag_to_array(size_flag, build_sizes, 0); + build_undistort_count = proxy_bitflag_to_array(size_flag, build_undistort_sizes, 1); + + if (clip->source == MCLIP_SRC_MOVIE) { + do_movie_proxy(pjv, build_sizes, build_count, build_undistort_sizes, + build_undistort_count, stop, do_update, progress); + } + else { + do_sequence_proxy(pjv, build_sizes, build_count, build_undistort_sizes, + build_undistort_count, stop, do_update, progress); + } +} + static void proxy_endjob(void *pjv) { ProxyJob *pj = pjv; @@ -1133,7 +1327,7 @@ void CLIP_OT_mode_set(wmOperatorType *ot) * that explains the negative signs in the code below */ -static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { if (event->type != NDOF_MOTION) return OPERATOR_CANCELLED; |