/* note: currently used by proxy job for movies, threading happens within single frame * (meaning scaling shall be threaded) */ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion, int cfra, int *build_sizes, int build_count, bool undistorted) { ImBuf *ibuf; MovieClipUser user; if (!build_count) return; user.framenr = cfra; user.render_flag = 0; user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP); if (ibuf) { ImBuf *tmpibuf = ibuf; int i; if (undistorted) tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf); for (i = 0; i < build_count; i++) movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true); IMB_freeImBuf(ibuf); if (tmpibuf != ibuf) IMB_freeImBuf(tmpibuf); } }
/* Get image buffer for a given frame * * Frame is in clip space. */ static ImBuf *tracking_context_get_frame_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag, int framenr) { ImBuf *ibuf; MovieClipUser new_user = *user; new_user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, framenr); ibuf = BKE_movieclip_get_ibuf_flag(clip, &new_user, clip_flag, MOVIECLIP_CACHE_SKIP); return ibuf; }
void MovieClipBaseOperation::initExecution() { if (this->m_movieClip) { BKE_movieclip_user_set_frame(this->m_movieClipUser, this->m_framenumber); ImBuf *ibuf; if (this->m_cacheFrame) ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, this->m_movieClipUser); else ibuf = BKE_movieclip_get_ibuf_flag(this->m_movieClip, this->m_movieClipUser, this->m_movieClip->flag, MOVIECLIP_CACHE_SKIP); if (ibuf) { this->m_movieClipBuffer = ibuf; if (ibuf->rect_float == NULL || ibuf->userflags & IB_RECT_INVALID) { IMB_float_from_rect(ibuf); ibuf->userflags &= ~IB_RECT_INVALID; } } } }
ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user) { return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0); }
void MovieClipNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const { NodeOutput *outputMovieClip = this->getOutputSocket(0); NodeOutput *alphaMovieClip = this->getOutputSocket(1); NodeOutput *offsetXMovieClip = this->getOutputSocket(2); NodeOutput *offsetYMovieClip = this->getOutputSocket(3); NodeOutput *scaleMovieClip = this->getOutputSocket(4); NodeOutput *angleMovieClip = this->getOutputSocket(5); bNode *editorNode = this->getbNode(); MovieClip *movieClip = (MovieClip *)editorNode->id; MovieClipUser *movieClipUser = (MovieClipUser *)editorNode->storage; bool cacheFrame = !context.isRendering(); ImBuf *ibuf = NULL; if (movieClip) { if (cacheFrame) ibuf = BKE_movieclip_get_ibuf(movieClip, movieClipUser); else ibuf = BKE_movieclip_get_ibuf_flag(movieClip, movieClipUser, movieClip->flag, MOVIECLIP_CACHE_SKIP); } // always connect the output image MovieClipOperation *operation = new MovieClipOperation(); operation->setMovieClip(movieClip); operation->setMovieClipUser(movieClipUser); operation->setFramenumber(context.getFramenumber()); operation->setCacheFrame(cacheFrame); converter.addOperation(operation); converter.mapOutputSocket(outputMovieClip, operation->getOutputSocket()); converter.addPreview(operation->getOutputSocket()); MovieClipAlphaOperation *alphaOperation = new MovieClipAlphaOperation(); alphaOperation->setMovieClip(movieClip); alphaOperation->setMovieClipUser(movieClipUser); alphaOperation->setFramenumber(context.getFramenumber()); alphaOperation->setCacheFrame(cacheFrame); converter.addOperation(alphaOperation); converter.mapOutputSocket(alphaMovieClip, alphaOperation->getOutputSocket()); MovieTrackingStabilization *stab = &movieClip->tracking.stabilization; float loc[2], scale, angle; loc[0] = 0.0f; loc[1] = 0.0f; scale = 1.0f; angle = 0.0f; if (ibuf) { if (stab->flag & TRACKING_2D_STABILIZATION) { int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(movieClip, context.getFramenumber()); BKE_tracking_stabilization_data_get(&movieClip->tracking, clip_framenr, ibuf->x, ibuf->y, loc, &scale, &angle); } } converter.addOutputValue(offsetXMovieClip, loc[0]); converter.addOutputValue(offsetYMovieClip, loc[1]); converter.addOutputValue(scaleMovieClip, scale); converter.addOutputValue(angleMovieClip, angle); if (ibuf) { IMB_freeImBuf(ibuf); } }
/* 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); }