void MovieDistortionOperation::initExecution() { this->m_inputOperation = this->getInputSocketReader(0); if (this->m_movieClip) { MovieClipUser clipUser = {0}; int calibration_width, calibration_height; BKE_movieclip_user_set_frame(&clipUser, this->m_framenumber); BKE_movieclip_get_size(this->m_movieClip, &clipUser, &calibration_width, &calibration_height); for (unsigned int i = 0; i < s_cache.size(); i++) { DistortionCache *c = (DistortionCache *)s_cache[i]; if (c->isCacheFor(this->m_movieClip, this->m_width, this->m_height, calibration_width, calibration_height, this->m_distortion)) { this->m_cache = c; this->m_cache->updateLastUsage(); return; } } DistortionCache *newC = new DistortionCache(this->m_movieClip, this->m_width, this->m_height, calibration_width, calibration_height, this->m_distortion); s_cache.push_back(newC); this->m_cache = newC; } else { this->m_cache = NULL; } }
void clip_graph_tracking_values_iterate_track( SpaceClip *sc, MovieTrackingTrack *track, void *userdata, void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float val), void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), void (*segment_end)(void *userdata, int coord)) { MovieClip *clip = ED_space_clip_get_clip(sc); int width, height, coord; BKE_movieclip_get_size(clip, &sc->user, &width, &height); for (coord = 0; coord < 2; coord++) { int i, prevfra = 0; bool open = false; float prevval = 0.0f; for (i = 0; i < track->markersnr; i++) { MovieTrackingMarker *marker = &track->markers[i]; float val; if (marker->flag & MARKER_DISABLED) { if (open) { if (segment_end) segment_end(userdata, coord); open = false; } continue; } if (!open) { if (segment_start) segment_start(userdata, track, coord); open = true; prevval = marker->pos[coord]; } /* value is a pixels per frame speed */ val = (marker->pos[coord] - prevval) * ((coord == 0) ? (width) : (height)); val /= marker->framenr - prevfra; if (func) { int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); func(userdata, track, marker, coord, scene_framenr, val); } prevval = marker->pos[coord]; prevfra = marker->framenr; } if (open) { if (segment_end) segment_end(userdata, coord); } } }
/* 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 *clip; MovieClipUser user = {0}; int file, len, width, height; const char *libname; char str[FILE_MAX], strtest[FILE_MAX]; BLI_strncpy(str, name, sizeof(str)); BLI_path_abs(str, G.main->name); /* exists? */ file = BLI_open(str, O_BINARY | O_RDONLY, 0); if (file == -1) return NULL; close(file); /* ** first search an identical clip ** */ for (clip = G.main->movieclip.first; clip; clip = clip->id.next) { BLI_strncpy(strtest, clip->name, sizeof(clip->name)); BLI_path_abs(strtest, G.main->name); if (strcmp(strtest, str) == 0) { BLI_strncpy(clip->name, name, sizeof(clip->name)); /* for stringcode */ clip->id.us++; /* officially should not, it doesn't link here! */ return clip; } } /* ** add new movieclip ** */ /* create a short library name */ len = strlen(name); while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--; libname = name + len; clip = movieclip_alloc(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; user.framenr = 1; BKE_movieclip_get_size(clip, &user, &width, &height); if (width && height) { clip->tracking.camera.principal[0] = ((float)width) / 2.0f; clip->tracking.camera.principal[1] = ((float)height) / 2.0f; clip->tracking.camera.focal = 24.0f * width / clip->tracking.camera.sensor_width; } movieclip_calc_length(clip); return clip; }
void ED_space_clip_get_aspect_dimension_aware(SpaceClip *sc, float *aspx, float *aspy) { int w, h; /* most of tools does not require aspect to be returned with dimensions correction * due to they're invariant to this stuff, but some transformation tools like rotation * should be aware of aspect correction caused by different resolution in different * directions. * mainly this is sued for transformation stuff */ if (!sc->clip) { *aspx = 1.0f; *aspy = 1.0f; return; } ED_space_clip_get_aspect(sc, aspx, aspy); BKE_movieclip_get_size(sc->clip, &sc->user, &w, &h); *aspx *= (float) w; *aspy *= (float) h; if (*aspx < *aspy) { *aspy = *aspy / *aspx; *aspx = 1.0f; } else { *aspx = *aspx / *aspy; *aspy = 1.0f; } }
static void draw_tracks_error_curves(SpaceClip *sc) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; TrackErrorCurveUserData data; data.clip = clip; data.tracking = tracking; data.tracking_object = BKE_tracking_object_get_active(tracking); data.active_track = BKE_tracking_track_get_active(tracking); data.matrix_initialized = false; BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height); data.aspy = 1.0f / tracking->camera.pixel_aspect; if (!data.width || !data.height) { return; } clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, &data, tracking_error_segment_point_cb, tracking_error_segment_start_cb, tracking_error_segment_end_cb); }
static void draw_tracks_curves(View2D *v2d, SpaceClip *sc) { MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); int width, height; struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } userdata; BKE_movieclip_get_size(clip, &sc->user, &width, &height); if(!width || !height) return; /* non-selected knot handles */ userdata.hsize= UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); userdata.sel= 0; userdata.act_track= act_track; UI_view2d_getscale(v2d, &userdata.xscale, &userdata.yscale); clip_graph_tracking_values_iterate(sc, &userdata, tracking_segment_knot_cb, NULL, NULL); /* draw graph lines */ glEnable(GL_BLEND); clip_graph_tracking_values_iterate(sc, act_track, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb); glDisable(GL_BLEND); /* selected knot handles on top of curves */ userdata.sel= 1; clip_graph_tracking_values_iterate(sc, &userdata, tracking_segment_knot_cb, NULL, NULL); }
void ED_space_clip_get_size(SpaceClip *sc, int *width, int *height) { if (sc->clip) { BKE_movieclip_get_size(sc->clip, &sc->user, width, height); } else { *width = *height = IMG_SIZE_FALLBACK; } }
static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { if (in[0]->data) { if (node->id) { MovieClip *clip = (MovieClip *)node->id; CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); CompBuf *stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 0); ImBuf *ibuf; ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); if (ibuf) { RenderData *rd = data; ImBuf *obuf; MovieTracking *tracking = &clip->tracking; int width, height; float overscan = 0.0f; MovieClipUser user = {0}; BKE_movieclip_user_set_frame(&user, rd->cfra); ibuf->rect_float = cbuf->rect; BKE_movieclip_get_size(clip, &user, &width, &height); if (!node->storage) node->storage = BKE_tracking_distortion_create(); if (node->custom1 == 0) obuf = BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 1); else obuf = BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 0); stackbuf->rect = obuf->rect_float; stackbuf->malloc = TRUE; obuf->mall &= ~IB_rectfloat; obuf->rect_float = NULL; IMB_freeImBuf(ibuf); IMB_freeImBuf(obuf); } /* pass on output and free */ out[0]->data = stackbuf; if (cbuf != in[0]->data) free_compbuf(cbuf); } else { CompBuf *cbuf = in[0]->data; CompBuf *stackbuf = pass_on_compbuf(cbuf); out[0]->data = stackbuf; } } }
void TrackPositionOperation::initExecution() { MovieTracking *tracking = NULL; MovieClipUser user = {0}; MovieTrackingObject *object; zero_v2(this->m_markerPos); zero_v2(this->m_relativePos); if (!this->m_movieClip) return; tracking = &this->m_movieClip->tracking; BKE_movieclip_user_set_frame(&user, this->m_framenumber); BKE_movieclip_get_size(this->m_movieClip, &user, &this->m_width, &this->m_height); object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName); if (object) { MovieTrackingTrack *track; track = BKE_tracking_track_get_named(tracking, object, this->m_trackName); if (track) { MovieTrackingMarker *marker; int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); marker = BKE_tracking_marker_get(track, clip_framenr); copy_v2_v2(this->m_markerPos, marker->pos); if (this->m_position == CMP_TRACKPOS_RELATIVE_START) { int i; for (i = 0; i < track->markersnr; i++) { marker = &track->markers[i]; if ((marker->flag & MARKER_DISABLED) == 0) { copy_v2_v2(this->m_relativePos, marker->pos); break; } } } else if (this->m_position == CMP_TRACKPOS_RELATIVE_FRAME) { int relative_clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_relativeFrame); marker = BKE_tracking_marker_get(track, relative_clip_framenr); copy_v2_v2(this->m_relativePos, marker->pos); } } } }
/* 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; int cfra, sfra = SFRA, efra = EFRA; if (pj->index_context) IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress); if (!build_undistort_count) { if (*stop) pj->stop = 1; return; } else { sfra = 1; efra = clip->len; } if (build_undistort_count) { int threads = BLI_system_thread_count(); int width, height; BKE_movieclip_get_size(clip, NULL, &width, &height); distortion = BKE_tracking_distortion_new(&clip->tracking, width, height); BKE_tracking_distortion_set_threads(distortion, threads); } for (cfra = sfra; cfra <= efra; cfra++) { BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, distortion, cfra, build_undistort_sizes, build_undistort_count, 1); if (*stop || G.is_break) break; *do_update = true; *progress = ((float) cfra - sfra) / (efra - sfra); } if (distortion) BKE_tracking_distortion_free(distortion); if (*stop) pj->stop = 1; }
void MovieClipBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { resolution[0] = 0; resolution[1] = 0; if (this->m_movieClip) { int width, height; BKE_movieclip_get_size(this->m_movieClip, this->m_movieClipUser, &width, &height); resolution[0] = width; resolution[1] = height; } }
static void movieclip_load_get_szie(MovieClip *clip) { int width, height; MovieClipUser user = {0}; user.framenr = 1; BKE_movieclip_get_size(clip, &user, &width, &height); if (width && height) { clip->tracking.camera.principal[0] = ((float)width) / 2.0f; clip->tracking.camera.principal[1] = ((float)height) / 2.0f; } else { clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK; } }
void KeyingScreenOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { resolution[0] = 0; resolution[1] = 0; if (this->m_movieClip) { MovieClipUser user = {0}; int width, height; int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); BKE_movieclip_user_set_frame(&user, clip_frame); BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height); resolution[0] = width; resolution[1] = height; } }
void TrackPositionOperation::executePixel(float *outputValue, float x, float y, PixelSampler sampler) { MovieClipUser user = {0}; MovieTracking *tracking = &movieClip->tracking; MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, this->trackingObject); MovieTrackingTrack *track; MovieTrackingMarker *marker; int width, height; outputValue[0] = 0.0f; if (!object) return; track = BKE_tracking_track_get_named(tracking, object, this->trackName); if (!track) return; BKE_movieclip_user_set_frame(&user, this->framenumber); BKE_movieclip_get_size(this->movieClip, &user, &width, &height); marker = BKE_tracking_marker_get(track, this->framenumber); outputValue[0] = marker->pos[this->axis]; if (this->relative) { int i; for (i = 0; i < track->markersnr; i++) { marker = &track->markers[i]; if ((marker->flag & MARKER_DISABLED) == 0) { outputValue[0] -= marker->pos[this->axis]; break; } } } if (this->axis == 0) outputValue[0] *= width; else outputValue[0] *= height; }
void PlaneTrackCommonOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { NodeOperation::determineResolution(resolution, preferredResolution); resolution[0] = 0; resolution[1] = 0; if (this->m_movieClip) { int width, height; MovieClipUser user = {0}; BKE_movieclip_user_set_frame(&user, this->m_framenumber); BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height); resolution[0] = width; resolution[1] = height; } }
void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[2]) { copy_v2_v2(r_co, co); if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { MovieClip *clip = ED_space_clip_get_clip(sc); float aspy = 1.0f / clip->tracking.camera.pixel_aspect; int width, height; BKE_movieclip_get_size(sc->clip, &sc->user, &width, &height); r_co[0] *= width; r_co[1] *= height * aspy; BKE_tracking_undistort_v2(&clip->tracking, r_co, r_co); r_co[0] /= width; r_co[1] /= height * aspy; } }
static void node_composit_exec_keyingscreen(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) { NodeKeyingScreenData *keyingscreen_data = node->storage; RenderData *rd = data; CompBuf *screenbuf = NULL; if (node->id) { MovieClip *clip = (MovieClip *) node->id; MovieClipUser user = {0}; int width, height; BKE_movieclip_user_set_frame(&user, rd->cfra); BKE_movieclip_get_size(clip, &user, &width, &height); screenbuf = alloc_compbuf(width, height, CB_RGBA, TRUE); compute_gradient_screen(rd, keyingscreen_data, clip, screenbuf); } out[0]->data = screenbuf; }
static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); int width, height; TrackMotionCurveUserData userdata; BKE_movieclip_get_size(clip, &sc->user, &width, &height); if (!width || !height) return; /* non-selected knot handles */ userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); userdata.sel = false; userdata.act_track = act_track; UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale); clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, &userdata, tracking_segment_knot_cb, NULL, NULL); /* draw graph lines */ glEnable(GL_BLEND); clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, act_track, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb); glDisable(GL_BLEND); /* selected knot handles on top of curves */ userdata.sel = true; clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, &userdata, tracking_segment_knot_cb, NULL, NULL); }
void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height) { #if 0 /* originally was needed to support image sequences with different image dimensions, * which might be useful for such things as reconstruction of unordered image sequence, * or painting/rotoscoping of non-equal-sized images, but this ended up in unneeded * cache lookups and even unwanted non-proxied files loading when doing mask parenting, * so let's disable this for now and assume image sequence consists of images with * equal sizes (sergey) */ if (user->framenr == clip->lastframe) { #endif if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) { *width = clip->lastsize[0]; *height = clip->lastsize[1]; } else { ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user); if (ibuf && ibuf->x && ibuf->y) { real_ibuf_size(clip, user, ibuf, width, height); } else { *width = clip->lastsize[0]; *height = clip->lastsize[1]; } if (ibuf) IMB_freeImBuf(ibuf); } } void BKE_movieclip_get_size_fl(MovieClip *clip, MovieClipUser *user, float size[2]) { int width, height; BKE_movieclip_get_size(clip, user, &width, &height); size[0] = (float)width; size[1] = (float)height; }
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) { int width, height; BKE_movieclip_get_size(clip, NULL, &width, &height); handle->distortion = BKE_tracking_distortion_new(&clip->tracking, width, height); } 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); } } }
void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes) { if (scopes->ok) return; if (scopes->track_preview) { IMB_freeImBuf(scopes->track_preview); scopes->track_preview = NULL; } scopes->marker = NULL; scopes->track = NULL; if (clip) { MovieTrackingTrack *act_track = BKE_tracking_active_track(&clip->tracking); if (act_track) { MovieTrackingTrack *track = act_track; MovieTrackingMarker *marker = BKE_tracking_get_marker(track, user->framenr); if (marker->flag & MARKER_DISABLED) { scopes->track_disabled = TRUE; } else { ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user); scopes->track_disabled = FALSE; if (ibuf && (ibuf->rect || ibuf->rect_float)) { ImBuf *tmpibuf; MovieTrackingMarker undist_marker = *marker; if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { int width, height; float aspy = 1.0f / clip->tracking.camera.pixel_aspect; BKE_movieclip_get_size(clip, user, &width, &height); undist_marker.pos[0] *= width; undist_marker.pos[1] *= height * aspy; BKE_tracking_invert_intrinsics(&clip->tracking, undist_marker.pos, undist_marker.pos); undist_marker.pos[0] /= width; undist_marker.pos[1] /= height * aspy; } /* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */ tmpibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */, 1 /* anchor */, scopes->track_pos, NULL); if (tmpibuf->rect_float) IMB_rect_from_float(tmpibuf); if (tmpibuf->rect) scopes->track_preview = tmpibuf; else IMB_freeImBuf(tmpibuf); } IMB_freeImBuf(ibuf); } if ((track->flag & TRACK_LOCKED) == 0) { scopes->marker = marker; scopes->track = track; scopes->slide_scale[0] = track->pat_max[0] - track->pat_min[0]; scopes->slide_scale[1] = track->pat_max[1] - track->pat_min[1]; } } } scopes->framenr = user->framenr; scopes->ok = TRUE; }
void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *userptr, PointerRNA *trackptr, int compact) { PropertyRNA *prop; uiBlock *block; uiBut *bt; PointerRNA clipptr; MovieClip *clip; MovieClipUser *user; MovieTrackingTrack *track; MovieTrackingMarker *marker; MarkerUpdateCb *cb; const char *tip; float pat_min[2], pat_max[2]; if (!ptr->data) return; prop = RNA_struct_find_property(ptr, propname); if (!prop) { printf("%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname); return; } if (RNA_property_type(prop) != PROP_POINTER) { printf("%s: expected pointer property for %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname); return; } clipptr = RNA_property_pointer_get(ptr, prop); clip = (MovieClip *)clipptr.data; user = userptr->data; track = trackptr->data; marker = BKE_tracking_marker_get(track, user->framenr); cb = MEM_callocN(sizeof(MarkerUpdateCb), "uiTemplateMarker update_cb"); cb->compact = compact; cb->clip = clip; cb->user = user; cb->track = track; cb->marker = marker; cb->marker_flag = marker->flag; cb->framenr = user->framenr; if (compact) { block = uiLayoutGetBlock(layout); if (cb->marker_flag & MARKER_DISABLED) tip = "Marker is disabled at current frame"; else tip = "Marker is enabled at current frame"; bt = uiDefIconButBitI(block, TOGN, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, 20, 20, &cb->marker_flag, 0, 0, 1, 0, tip); uiButSetNFunc(bt, marker_update_cb, cb, NULL); } else { int width, height, step, digits; float pat_dim[2], search_dim[2], search_pos[2]; uiLayout *col; BKE_movieclip_get_size(clip, user, &width, &height); if (track->flag & TRACK_LOCKED) { uiLayoutSetActive(layout, FALSE); block = uiLayoutAbsoluteBlock(layout); uiDefBut(block, LABEL, 0, "Track is locked", 0, 0, 300, 19, NULL, 0, 0, 0, 0, ""); return; } step = 100; digits = 2; BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); sub_v2_v2v2(pat_dim, pat_max, pat_min); sub_v2_v2v2(search_dim, marker->search_max, marker->search_min); add_v2_v2v2(search_pos, marker->search_max, marker->search_min); mul_v2_fl(search_pos, 0.5); to_pixel_space(cb->marker_pos, marker->pos, width, height); to_pixel_space(cb->marker_pat, pat_dim, width, height); to_pixel_space(cb->marker_search, search_dim, width, height); to_pixel_space(cb->marker_search_pos, search_pos, width, height); to_pixel_space(cb->track_offset, track->offset, width, height); cb->marker_flag = marker->flag; block = uiLayoutAbsoluteBlock(layout); uiBlockSetHandleFunc(block, marker_block_handler, cb); uiBlockSetNFunc(block, marker_update_cb, cb, NULL); if (cb->marker_flag & MARKER_DISABLED) tip = "Marker is disabled at current frame"; else tip = "Marker is enabled at current frame"; uiDefButBitI(block, OPTIONN, MARKER_DISABLED, B_MARKER_FLAG, "Enabled", 10, 190, 145, 19, &cb->marker_flag, 0, 0, 0, 0, tip); col = uiLayoutColumn(layout, TRUE); uiLayoutSetActive(col, (cb->marker_flag & MARKER_DISABLED) == 0); block = uiLayoutAbsoluteBlock(col); uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Position:", 0, 190, 300, 19, NULL, 0, 0, 0, 0, ""); uiDefButF(block, NUM, B_MARKER_POS, "X:", 10, 171, 145, 19, &cb->marker_pos[0], -10 * width, 10.0 * width, step, digits, "X-position of marker at frame in screen coordinates"); uiDefButF(block, NUM, B_MARKER_POS, "Y:", 165, 171, 145, 19, &cb->marker_pos[1], -10 * height, 10.0 * height, step, digits, "Y-position of marker at frame in screen coordinates"); uiDefBut(block, LABEL, 0, "Offset:", 0, 152, 300, 19, NULL, 0, 0, 0, 0, ""); uiDefButF(block, NUM, B_MARKER_OFFSET, "X:", 10, 133, 145, 19, &cb->track_offset[0], -10 * width, 10.0 * width, step, digits, "X-offset to parenting point"); uiDefButF(block, NUM, B_MARKER_OFFSET, "Y:", 165, 133, 145, 19, &cb->track_offset[1], -10 * height, 10.0 * height, step, digits, "Y-offset to parenting point"); uiDefBut(block, LABEL, 0, "Pattern Area:", 0, 114, 300, 19, NULL, 0, 0, 0, 0, ""); uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Width:", 10, 95, 300, 19, &cb->marker_pat[0], 3.0f, 10.0 * width, step, digits, "Width of marker's pattern in screen coordinates"); uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Height:", 10, 76, 300, 19, &cb->marker_pat[1], 3.0f, 10.0 * height, step, digits, "Height of marker's pattern in screen coordinates"); uiDefBut(block, LABEL, 0, "Search Area:", 0, 57, 300, 19, NULL, 0, 0, 0, 0, ""); uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "X:", 10, 38, 145, 19, &cb->marker_search_pos[0], -width, width, step, digits, "X-position of search at frame relative to marker's position"); uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "Y:", 165, 38, 145, 19, &cb->marker_search_pos[1], -height, height, step, digits, "X-position of search at frame relative to marker's position"); uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Width:", 10, 19, 300, 19, &cb->marker_search[0], 3.0f, 10.0 * width, step, digits, "Width of marker's search in screen soordinates"); uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Height:", 10, 0, 300, 19, &cb->marker_search[1], 3.0f, 10.0 * height, step, digits, "Height of marker's search in screen soordinates"); uiBlockEndAlign(block); } }
void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes) { if (scopes->ok) return; if (scopes->track_preview) { IMB_freeImBuf(scopes->track_preview); scopes->track_preview = NULL; } if (scopes->track_search) { IMB_freeImBuf(scopes->track_search); scopes->track_search = NULL; } scopes->marker = NULL; scopes->track = NULL; scopes->track_locked = true; if (clip) { MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking); if (act_track) { MovieTrackingTrack *track = act_track; int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); scopes->marker = marker; scopes->track = track; if (marker->flag & MARKER_DISABLED) { scopes->track_disabled = true; } else { ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user); scopes->track_disabled = false; if (ibuf && (ibuf->rect || ibuf->rect_float)) { MovieTrackingMarker undist_marker = *marker; if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { int width, height; float aspy = 1.0f / clip->tracking.camera.pixel_aspect; BKE_movieclip_get_size(clip, user, &width, &height); undist_marker.pos[0] *= width; undist_marker.pos[1] *= height * aspy; BKE_tracking_undistort_v2(&clip->tracking, undist_marker.pos, undist_marker.pos); undist_marker.pos[0] /= width; undist_marker.pos[1] /= height * aspy; } scopes->track_search = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, true, true); scopes->undist_marker = undist_marker; scopes->frame_width = ibuf->x; scopes->frame_height = ibuf->y; scopes->use_track_mask = track->flag & TRACK_PREVIEW_ALPHA; } IMB_freeImBuf(ibuf); } if ((track->flag & TRACK_LOCKED) == 0) { float pat_min[2], pat_max[2]; scopes->track_locked = false; /* XXX: would work fine with non-transformed patterns, but would likely fail * with transformed patterns, but that would be easier to debug when * we'll have real pattern sampling (at least to test) */ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); scopes->slide_scale[0] = pat_max[0] - pat_min[0]; scopes->slide_scale[1] = pat_max[1] - pat_min[1]; } } } scopes->framenr = user->framenr; scopes->ok = true; }
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; TaskScheduler *task_scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; int sfra = SFRA, efra = EFRA; ProxyThread *handles; int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler); int width, height; ProxyQueue queue; if (build_undistort_count) { BKE_movieclip_get_size(clip, NULL, &width, &height); } 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; task_pool = BLI_task_pool_create(task_scheduler, &queue); handles = MEM_callocN(sizeof(ProxyThread) * tot_thread, "proxy threaded handles"); for (i = 0; i < tot_thread; i++) { ProxyThread *handle = &handles[i]; handle->clip = clip; 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(&clip->tracking, width, height); } BLI_task_pool_push(task_pool, proxy_task_func, handle, false, TASK_PRIORITY_LOW); } BLI_task_pool_work_and_wait(task_pool); BLI_task_pool_free(task_pool); if (build_undistort_count) { for (i = 0; i < tot_thread; i++) { ProxyThread *handle = &handles[i]; BKE_tracking_distortion_free(handle->distortion); } } BLI_spin_end(&queue.spin); MEM_freeN(handles); }
static void marker_block_handler(bContext *C, void *arg_cb, int event) { MarkerUpdateCb *cb = (MarkerUpdateCb *) arg_cb; MovieTrackingMarker *marker; int width, height, ok = FALSE; BKE_movieclip_get_size(cb->clip, cb->user, &width, &height); marker = BKE_tracking_marker_ensure(cb->track, cb->framenr); if (event == B_MARKER_POS) { marker->pos[0] = cb->marker_pos[0] / width; marker->pos[1] = cb->marker_pos[1] / height; /* to update position of "parented" objects */ DAG_id_tag_update(&cb->clip->id, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); ok = TRUE; } else if (event == B_MARKER_PAT_DIM) { float dim[2], pat_dim[2], pat_min[2], pat_max[2]; float scale_x, scale_y; int a; BKE_tracking_marker_pattern_minmax(cb->marker, pat_min, pat_max); sub_v2_v2v2(pat_dim, pat_max, pat_min); dim[0] = cb->marker_pat[0] / width; dim[1] = cb->marker_pat[1] / height; scale_x = dim[0] / pat_dim[0]; scale_y = dim[1] / pat_dim[1]; for (a = 0; a < 4; a++) { cb->marker->pattern_corners[a][0] *= scale_x; cb->marker->pattern_corners[a][1] *= scale_y; } BKE_tracking_marker_clamp(cb->marker, CLAMP_PAT_DIM); ok = TRUE; } else if (event == B_MARKER_SEARCH_POS) { float delta[2], side[2]; sub_v2_v2v2(side, cb->marker->search_max, cb->marker->search_min); mul_v2_fl(side, 0.5f); delta[0] = cb->marker_search_pos[0] / width; delta[1] = cb->marker_search_pos[1] / height; sub_v2_v2v2(cb->marker->search_min, delta, side); add_v2_v2v2(cb->marker->search_max, delta, side); BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_POS); ok = TRUE; } else if (event == B_MARKER_SEARCH_DIM) { float dim[2], search_dim[2]; sub_v2_v2v2(search_dim, cb->marker->search_max, cb->marker->search_min); dim[0] = cb->marker_search[0] / width; dim[1] = cb->marker_search[1] / height; sub_v2_v2(dim, search_dim); mul_v2_fl(dim, 0.5f); cb->marker->search_min[0] -= dim[0]; cb->marker->search_min[1] -= dim[1]; cb->marker->search_max[0] += dim[0]; cb->marker->search_max[1] += dim[1]; BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_DIM); ok = TRUE; } else if (event == B_MARKER_FLAG) { marker->flag = cb->marker_flag; ok = TRUE; } else if (event == B_MARKER_OFFSET) { float offset[2], delta[2]; int i; offset[0] = cb->track_offset[0] / width; offset[1] = cb->track_offset[1] / height; sub_v2_v2v2(delta, offset, cb->track->offset); copy_v2_v2(cb->track->offset, offset); for (i = 0; i < cb->track->markersnr; i++) sub_v2_v2(cb->track->markers[i].pos, delta); /* to update position of "parented" objects */ DAG_id_tag_update(&cb->clip->id, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); ok = TRUE; } if (ok) WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, cb->clip); }
/* Refine marker's position using previously known keyframe. * Direction of searching for a keyframe depends on backwards flag, * which means if backwards is false, previous keyframe will be as * reference. */ void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker, bool backwards) { MovieTrackingMarker *reference_marker = NULL; ImBuf *reference_ibuf, *destination_ibuf; float *search_area, *mask = NULL; int frame_width, frame_height; int search_area_height, search_area_width; int clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS; int reference_framenr; MovieClipUser user = {0}; double dst_pixel_x[5], dst_pixel_y[5]; bool tracked; /* Construct a temporary clip used, used to acquire image buffers. */ user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height); /* Get an image buffer for reference frame, also gets reference marker. */ if (!refine_marker_reference_frame_get(track, marker, backwards, &reference_framenr)) { return; } reference_ibuf = tracking_context_get_reference_ibuf(clip, &user, clip_flag, track, reference_framenr, backwards, &reference_marker); if (reference_ibuf == NULL) { return; } /* Could not refine with self. */ if (reference_marker == marker) { return; } /* Destination image buffer has got frame number corresponding to refining marker. */ destination_ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP); if (destination_ibuf == NULL) { IMB_freeImBuf(reference_ibuf); return; } /* Get search area from reference image. */ search_area = track_get_search_floatbuf(reference_ibuf, track, reference_marker, &search_area_width, &search_area_height); /* If needed, compute track's mask. */ if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker); /* Run the tracker from reference frame to current one. */ tracked = configure_and_run_tracker(destination_ibuf, track, reference_marker, marker, search_area, search_area_width, search_area_height, mask, dst_pixel_x, dst_pixel_y); /* Refine current marker's position if track was successful. */ if (tracked) { tracking_set_marker_coords_from_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y); marker->flag |= MARKER_TRACKED; } /* Free memory used for refining */ MEM_freeN(search_area); if (mask) MEM_freeN(mask); IMB_freeImBuf(reference_ibuf); IMB_freeImBuf(destination_ibuf); }